18 Jan 2017 10:59 +0000
闭包是 JavaScript 新手最容易遇到的一个问题, 之所以说新手, 是因为闭包在 JavaScript 中出现得非常频繁, 是理解 JavaScript 这门语言必须掌握的概念.
最经典的闭包案例:
const arr = ['a', 'b', 'c', 'd']; // 以下所有代码都用该数据
let i;
for (i = 0; i < arr.length; i++) {
setTimeout(() => {
console.log('Index: ' + i);
}, 200);
}
显然, 代码作者的预期结果是:
Index: 0
Index: 1
Index: 2
Index: 3
但是很可惜, 以上代码将在 200ms 后输出 4 次 'Index: 4', 因为在setTimeout()
中形成了闭包, 在该闭包中访问了外部变量i
, 但是i
在 200ms 后已经变成 4, 因此造成所有的输出都是 4.
解决方案:
传递中间变量
let i;
for (i = 0; i < arr.length; i++) {
// 通过传递变量 i, 使每个函数都获取到正确的索引
setTimeout(((i_local) => {
return () => {
console.log('Index: ' + i_local);
}
})(i), 1000);
}
如果你对 ES6 的特性或立即调用不熟悉, 以上代码等价于:
let i;
function temp(i) {
return function () {
console.log('Index: ' + i);
}
}
for (i = 0; i < arr.length; i++) {
// 通过传递变量 i, 使每个函数都获取到正确的索引
setTimeout(temp(i), 1000);
}
利用 let 的特性
for (let i = 0; i < arr.length; i++) {
setTimeout(() => {
console.log('Index: ' + i);
}, 1000);
}
let 会在每次调用时生成新的引用, 即每次调用时 let 是不同的, 所以最后输出不会全是 4.
Loading comments...