作用域
js的作用域有3种,分别是全局作用域,局部作用域,块级作用域(ES6新增)。
全局作用域:在函数function以外定义的变量是全局变量,具有全局作用域,在任何地方都可以访问
let a = 1; function x() { console.log(a); } x();
x()函数中并未声明变量a,但上面代码执行后会打印出1
局部作用域:在函数function内定义的变量为局部变量,具有局部作用域,函数内部都可以访问
function x() { let a = 1; } console.log(a);
x()函数中定义了变量a,但在函数外部打印变量a会报错,提示a没有定义
块级作用域:在{}括号内定义的变量,具有块级作用域,{}以外无法访问,比如if判断和for循环中
if (true) { let a = 1; } console.log(a);
打印变量a会报错,提示a没有定义
自由变量
其实除上述3种变量外,还有一种特殊的变量叫自由变量。
自由变量:一个变量在当前作用域中(也就是上述3种作用域)没有被定义,但却被使用了
let a = 1; function x() { let b = 2; function y() { console.log(a + b); } y(); } x();
x()函数执行后,结果为3,为什么y()中没有定义变量a和b,但控制台却能打印出结果3呢?
因为自由变量会像上级作用域一层一层的寻找,直至找到为止。所以当y()函数执行打印a+b时,
虽然y()函数中没有定义变量a和b,但它会往上一级去寻找,这里的上一级是x()函数,但它只定义了变量b,
因此会接着往上寻找,最后找到了x()函数外定义的全局变量a。
注:如果全局作用域都没有找到,则会报错xxx is not defined
闭包
闭包可简单理解为作用域应用的2种特别情况:
1. 函数作为返回值被返回
2. 函数作为参数被传递
上面2个示例执行代码后,a的值都为100, 你可能会有疑惑, 为什么a都是100呢?
明明在函数执行之前已经重新定义了变量a的值,下面用大神总结的一句话就可迎刃而解
总结:所有自由变量的查找是在函数定义的地方,向上级作用域一层一层往上查找,而不是在执行的地方
红色框部分就是函数定义的地方,然后向上级作用域寻找,a的值为100