[[scope]]是每一个JavaScript函数都有得一个对象,对象中有些属性我们可以访问,但是有些不可以,这些属性仅供JavaScript引擎存取,[[scope]]就是其中一个。[[scope]]指的就是哦我们所说得作用域,其中储存了执行期上下文得集合。
执行期上下文:当函数运行时,会创建一个称为执行期上下文得内部对象。一个执行期上下文定义了一个函数执行时得环境,函数每次执行时对应的执行上下文是独一无二的所以多次调用一个函数会多次创建多个执行期上下文,当函数执行完毕,它所产生的执行期上下文将被销毁。
作用域链:[[scope]] 中所储存得执行期上下文对象得集合,这个集合成链式链接,我们把这种链式链接叫做作用域链。
比如:
function a() { }
a函数被定义的时候,a的作用域链 a.[[scope]] --> 0:aGO{}
当a函数被执行的时候,a.[[scope]] --> 0:aAO{}
1:GO{}
当a被执行完了之后,aAO{}就会被销毁。a的作用域链又回到了被定义的状态。当a再次被执行的时候,还会再创建一个全新的aAO{}对象,然后放在a的作用域链的最顶端。(关于AO和GO的介绍,请查看JavaScript的预编译)
var temp = 123; function a() { var temp = 345; console.log(temp); }a();
在上面这个程序中,运行的结果是345;因为a执行的时候a.[[scope]] --> 0:aAO{ temp = 345}
1:GO{temp = 123}
程序会现在作用域的最顶端的0:aAO中找需要打印的变量temp,在aAO中找到了,就用这个temp,所以打印的结果就是345,当把a函数中的“var temp = 345;”去掉的话那么a的aAO中就不存在temp这个变量,这时候就会到作用域链的下一个去查找。在本例中,就是在GO中查找,在GO中找到了,就打印这个GO中的temp。如果找遍了都不存在的话,就报错,说使用了未声明的变量。
function a() { function b() { } b(); }
在这个例子中,a被定义是创建了a的执行期上下文,a.[[scope]] --> 0:aAO{ }
1:GO{ }
而b是在a函数中定义的,那么b在运行时的执行期上下文应该是这样的b.[[scope]] --> 0:bAO{ }
1:a.[[scope]]
也就是b.[[scope]] --> 0:bAO{ }
1:aAO{ }
2:GO{ }
原文地址:https://www.cnblogs.com/xiaonongfu/p/11002863.html