这段code是不是闭包?
发布于 6 年前 作者 CollapsarLi 2951 次浏览 来自 问答

下面这段code 来自阮一峰大大的ECMAScript 6 入门,讲的是let的用法 第一种: var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a [6] (); // 10 第二种: var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a [6] (); // 6 阮大大给出的解释是: 变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。这个是可以理解。

我的疑问是:let声明的10个i为什么没有被释放掉? 我的理解: 因为function 函数是在for块内,所以function 可以访问for中的局部变量 i。而function又被赋值给了全局变量a[],这就会导致那个10个不同的 i 不会被回收掉。 那么这算不算是一种闭包?

8 回复

这个不叫闭包,叫作用域。

这是block scope里的 let loops 参考You don’t know js

for (let i=0; i<10; i++) {
	console.log( i );
}
console.log( i ); // ReferenceError

可以理解为

{
	let j;
	for (j=0; j<10; j++) {
		let i = j; // re-bound for each iteration!
		console.log( i );
	}
}

PS: 别看阮一峰了

首先感谢楼上两位小伙伴的回复。 我完全可以理解 let 的作用, 我的疑问是在为什么第二种 i 为什么没有被释放掉。楼上两位小伙伴的讨论都是let 作用域的问题。 我想知道的是 a[6] 这里发生了什么

@CollapsarLi 因为console.log( i )引用到了, i 就不会被回收

我们可以换一种方式

var a=[];
for(let i = {count: 0}; i.count < 10; i.count++) {
    a[i.count] = function() {
        console.log(i, i.count);
    };
}
a[6](); // {count: 10} 10

很显然,在for语句中的i没有被释放掉,而且因为传对象引用,所有a都拿到了同一个i对象 这确实是形成了一个闭包(a[i.count]函数内部引用了外部的变量(i)) 因此i不会被释放掉 可以用调试工具一步步查看这个过程

感谢楼上各位大佬的指点。已经理解这个问题了

一个引用自由变量的函数就是闭包。

好好体会下「自由变量」

变量执行环境

回到顶部