在JavaScript中使用闭包时范围内变量的值

时间:2017-01-08 08:58:18

标签: javascript variables scope closures

你能解释这三段代码之间的区别吗?它们看起来与我相同,但输出结果不同。

1:

var i;

function print(){return function(){console.log(b)}};

function doSetTimeout(b){setTimeout(print(),2000);};

for(i=0;i<10;i++){doSetTimeout(i)}

2:

var i;

function print(){console.log(b)};

function doSetTimeout(b){setTimeout(print,2000);};

for(i=0;i<10;i++){doSetTimeout(i)}

3:

var i;

function doSetTimeout(b){setTimeout(function(){console.log(b)},2000);};

for(i=0;i<10;i++){doSetTimeout(i)}

前2个返回b为未定义,而第3个返回预期值。

1 个答案:

答案 0 :(得分:0)

在你给出的前两个例子中,你没有将b传递给print(),所以print无法通过查看它的词法父母来找到该变量。

当您传递函数值时,闭包不会发生,以print作为参数,只要定义了setTimeout()并且实际调用了print(),它就会发生。因此,您无法访问自己认为的上下文。

在最后一个例子中它无论如何都有效,因为你定义正在执行的函数内部的匿名函数已经知道b是什么,所以b是可用的。

&#34;当给定的执行上下文遇到代码中的函数定义时,会创建一个新的函数对象,其内部属性名为[[scope]](如词法作用域),它引用当前的VariableEnvironment。 (ES 5 13.0-2)

每个函数都获得一个[[scope]]属性,并且在调用该函数时,scope属性的值被赋值给其VariableEnvironment的外部词法环境引用(或outerLex)属性。 (ES 5 10.4.3.5-7)这样,每个VariableEnvironment都继承自其词法父类的VariableEnvironment。此范围链从全局对象开始运行词法层次结构的长度。&#34;

来源:

https://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/

也很好读:

http://davidshariff.com/blog/what-is-the-execution-context-in-javascript/