1、作用域:JavaScript里的作用域分为:全局作用域、函数作用域、块级作用域
- 全局作用域:在全局对象(window)中声明的变量和函数具有全局作用域,程序的所有部位都可见。
- 函数作用域:在一个函数内部声明的变量和函数具有局部作用域,只在函数内部可见,若在函数外部访问会返回undefined。这里注意一点:带参的函数,参数列表中的参数也相当于是声明了的局部变量,在函数内部不需要再次声明,直接调用即可。若函数对象中和全局对象中同时对一个变量声明/赋值,在函数内部以函数内的声明/赋值为准。
- 块级作用域:用let/const声明的变量只在{}块级符号内部可见(es6新特性)。且const是声明一个常量,在作用域内部不能改变,否则会报错。
2、作用域链:函数中嵌套一个函数...。嵌套的函数可以通过作用域链访问外部函数的变量,在自己没有声明的情况下。
例子:
- 带参的函数
var a=10;
function f(a){
a++;
console.log(a);
}
f(a);//11 这里出现的a变量,会将变量a中的值复制一份到这里。实际上全局变量的值并没有改变
console.log(a);//10
2.不带参的函数,函数内部声明了和全局一样的变量并赋值
var a=10;
function f(){
var a=100;
a++;
console.log(a);
}
f(a);//101
console.log(a);//10,这里其实就与全局中的a变量完全无关了。全局中的a就是个吃瓜群众。
3.不带参的函数,函数内部声明了和全局一样的变量但不进行赋值
var a=10;
function f(){
var a;
a++;
console.log(a);
}
f(a);//NaN
console.log(a);//10 这里的全局对象中的a也是吃瓜群众
对于出现NaN的解释:在函数内部对变量a进行了声明,因此在对a进行操作时不会到全局中去寻找。但函数内部没有对a进行赋值,未赋值的变量的值为 undefined。对undefined++,返回NaN(not a number),undefined想转换为数字但是转换失败。
4.不带参数的函数,且在函数内部不进行声明就操作变量(这就涉及作用域链了)
var a=10;
function f(){
a++;
console.log(a);
}
f(a);//11
console.log(a);//11 注意:这里的全局中的变量发生了改变
当嵌套函数(暂且这么叫吧)的内部没有对变量进行声明,就进行操作时,此时(假如执行函数的有一个小人,那么这个小人)就会沿着当前函数的活动对象(正在执行的函数会生成一个活动对象,来保存函数需要用到的变量和函数)的scope的指向到父级作用域(这里为全局作用域)中去寻找这个变量,若找到了,就在原地继续执行程序。当这个函数执行完毕后。
注意!这里的父级作用域中的变量的值也发生了改变!这里没有赋值,小人沿着作用域链找到了变量,并就在父级作用域中执行了操作,因此,父级函数中的变量也发生了改变。