作用域链与闭包
2019-02-15 本文已影响0人
Luigi_Lin
作用域链 Scope Chain
作用域链是一条变量对象组成的链,与执行上下文有关,用于处理标识符时进行变量查询。
函数拥有一个内部属性[[scope]],该属性由ES3规范定义,只能被JS引擎读写。[[scope]]包含一个函数被创建的作用域中对象的集合,这个集合就是作用域链。
灵魂图例.png
函数执行时,没遇到一个变量,都会在作用域链中进行查找。按顺序查AO/VO,遍历对象中的键,寻找同名标识符。若该变量对象中无同名标识符,则查找下一个VO。如果遍历完作用域链还没找到,则会抛出 * is not defined 的错误。
这就是shadow的原因,当在不同一个VO中由同名标识符时,会取前一个的值,此时后一个就被shadow了。
作用域链在代码执行时只会被with及catch改变。
- with
with语句传入的对象会被插入作用域链的首位。 - catch
catch语句会把捕获到的异常插入作用域链的首位。
闭包 closures
定义
有权访问另一个函数作用域中变量的函数——红宝书
能够访问自由变量(函数中既非函数参数arguments亦非局部变量的变量)的函数——MDN
当闭包被创建时,闭包的[[scope]]属性被初始化,[[scope]]包含了与执行环境作用域链相同的对象的引用。
例如:
var x = 10;
function test(){
console.log(x);
}
(()=>{
var x = 20;
test(); //10
})();
因为[[scope]]时创建执行上下文时就创建的,作用域链时这个时候确定的,是静态词法链。
Function构造器创建的函数[[scope]]只包含全局对象
例如:
var x = 10;
function test(){
var y = 20;
var test1 = Function('console.log(x)');
var test2 = Function('console.log(y)');
test1(); //10
test2(); // Uncaught ReferenceError: y is not defined
}
test();