先解释下什么是自由变量。
在A作用域中定义的变量,却没有在A作用域中声明,对于A作用域来说,x就是一个自由变量。
在上面代码中,在调用fn()函数时,函数体中第6行。取b得值就直接可以在fn作用域中取,因为b就是在这里定义的。而取x得值时就需要到另一个作用域中去取,即它的上面一层作用域。
其实,也不一定是上面一层,例如:
因此,取变量时,要到创建这个函数的那个作用域中取值——是“创建”,而不是“调用”,切记切记——其实这就是所谓的“静态作用域”。
总结一下取自由变量的这个作用域链的过程:(假设a是自由变量)
第一步:先在当前作用域中查找a,如果有则获取并结束,如果没有则继续。
第二步:如果当前作用域是全局作用域,则证明a未定义,结束;否则继续
第三步:(不是全局作用域,那就是函数作用域)将创建该函数的作用域当做当前作用域
第四步:跳转到第一步
1 var a=10; 2 3 function fn(){ 4 var b=20; 5 6 function bar(){ 7 console.log(a+b); 8 } 9 10 return bar; 11 } 12 13 var x=fn(); 14 b=200; 15 16 x();
上面代码中,第13行,fn函数返回的是bar函数,赋值给x,因此第16行,执行x()就是执行bar函数,取b得值时直接在fn作用域中取。取a得值时bar作用域和fn作用域中都没有,只能往上到全局作用域中去取。