function f() {
function makeClosure(x) {
return function(){
return x;
}
}
var a = [];
var i;
for(i = 0; i < 3; i++) {
a[i] = makeClosure(i);
}
return a;
}
var gg = f()
gg[1]()
我非常接近理解闭合我可以品尝它:)...我得到了机制,我仍然只是在构思上有点麻烦。
我确信这是一个过时的过度简化,但在上述情况下,以下列方式思考发生的事情是否准确?
对不起,如果它长篇大论,我只是想让我的理解并非完全有缺陷。谢谢!
答案 0 :(得分:1)
由于这是一个寻求对闭包的一般理解的问题,这里是一般规则。
If a function is declared within another function as opposed to invoked (this is an important distinction), the inner function has access to the scope of the function it is declared in.
现在谈谈这个问题的具体细节。 第6点之后的所有内容看起来都与目前发布的代码不同。因此,我将仅描述循环正在做什么。
循环从0到2,用函数填充数组。在这些函数的范围内,它们分别具有值0,1和2.因此,最后一行gg[1]()
调用数组索引1处的函数,该函数返回值1.
另一种概念化的方法是在循环期间创建一个具有属性x的对象。该对象有一个无名方法,它返回x。
希望这能让您更好地了解闭包是什么。就个人而言,我喜欢将闭包视为范围规则而不一定是一种对象。
答案 1 :(得分:0)
- 函数f()被称为
醇>
首先,建立全局代码环境,并处理f
和gg
的声明。然后语句分配给gg
,这会导致f
被调用。
2
。调用函数makeClosure并赋予参数index [1]
还没有。循环开始后调用该函数(#5)。
当调用f
时,会创建一个新的执行上下文并建立其环境,makeClosure
,a
和i
被创建为局部变量,即全局对象放在其范围链上。然后为a
分配一个新的empy数组。
3
。函数makeClosure调用匿名函数并赋予它参数index [1]
makeClosure
内没有来电。
4
。声明开始 。5
。 for语句迭代然后调用函数makeClosure
这发生在2之前。
最初调用 makeClosure
,其值为0
。
调用makeClosure
时,会创建一个新的执行上下文。它有一个形式参数x
,第一次分配值0
,第二次分配1
,依此类推。
makeClosure
的范围链上有f
的执行对象,因此它可以访问所有f
的参数和变量。 Samed命名的标识符被本地标识符“shaddowed”。
每次调用时,makeClosure
都会返回一个没有变量或形式参数的函数对象。这些函数对象有一个范围链,它在创建它们时定义并包含它们自己,然后是makeClosure
的执行上下文的实例,然后是f
,然后是全局执行上下文。 / p>
返回的函数对象被分配给a
的成员。
6
。函数makeclosure然后测试参数index [0]是否与匿名函数的参数匹配7
。 makeClosure函数和匿名函数不匹配8
。循环迭代第二次产生参数索引[1]9
。函数makeclosure然后测试参数index [1]是否与匿名函数的参数匹配10
。他们匹配11
。退出makeClosure函数,函数f()返回var a,此时保存为数字1
这一切都没发生。对于每个循环,对makeClosure
进行了新的调用,因此返回一个新函数,在其作用域链上使用不同的makeClosure
执行对象实例。这些已分配给a
的成员。
for循环迭代3次,其中i
的值为0
,1
则为2
。当i
到达3
时,它会在执行前退出。
12
。返回对数组(a
)的引用并将其分配给全局g
。
13
。调用g[1]
。这引用了第二个返回的函数,然后调用它。当在其作用域链中解析该函数内的标识符x
时,会找到创建它的x
实例中的makeClosure
。这对应于使用值1创建的值,因此x
的值为1
,将返回。
我可能搞砸了一些东西,但这或多或少都在发生。