为什么让set和var绑定使用setTimeout函数表现不同? [英] Why let and var bindings behave differently using setTimeout function?
问题描述
此代码记录 6
,6次:
(function timer() {
for (var i=0; i<=5; i++) {
setTimeout(function clog() {console.log(i)}, i*1000);
}
})();
但这段代码......
But this code...
(function timer() {
for (let i=0; i<=5; i++) {
setTimeout(function clog() {console.log(i)}, i*1000);
}
})();
...记录以下结果:
... logs the following result:
0
1
2
3
4
5
为什么?
是因为让
以不同的方式绑定每个项目的内部范围, var
保持的最新值
?
Is it because let
binds to the inner scope each item differently and var
keeps the latest value of i
?
推荐答案
使用 var
,您有一个功能范围,只有一个共享所有循环迭代的绑定 - 即每个setTimeout回调中的 i
意味着 最终相同的相同的变量在循环迭代结束后到6。
With var
you have a function scope, and only one shared binding for all of your loop iterations - i.e. the i
in every setTimeout callback means the same variable that finally is equal to 6 after the loop iteration ends.
使用 让
你有一个块范围当在中用于
循环时,你会得到每次迭代的新绑定 - 即每个setTimeout回调中的 i
意味着一个不同的变量,每个变量都有不同的值:第一个是0,即下一个是1等。
With let
you have a block scope and when used in the for
loop you get a new binding for each iteration - i.e. the i
in every setTimeout callback means a different variable, each of which has a different value: the first one is 0, the next one is 1 etc.
所以这个:
(function timer() {
for (let i = 0; i <= 5; i++) {
setTimeout(function clog() { console.log(i); }, i * 1000);
}
})();
相当于仅使用var:
(function timer() {
for (var j = 0; j <= 5; j++) {
(function () {
var i = j;
setTimeout(function clog() { console.log(i); }, i * 1000);
}());
}
})();
使用立即调用的函数表达式来使用函数作用域,其方式与示例中的块作用域类似使用让
。
using immediately invoked function expression to use function scope in a similar way as the block scope works in the example with let
.
如果不使用 j $ c,可以写得更短$ c> name,但也许它不会那么清楚:
It could be written shorter without using the j
name, but perhaps it would not be as clear:
(function timer() {
for (var i = 0; i <= 5; i++) {
(function (i) {
setTimeout(function clog() { console.log(i); }, i * 1000);
}(i));
}
})();
箭头功能更短:
(() => {
for (var i = 0; i <= 5; i++) {
(i => setTimeout(() => console.log(i), i * 1000))(i);
}
})();
(但如果你可以使用箭头功能,则没有理由使用 var
。)
(But if you can use arrow functions, there's no reason to use var
.)
这是Babel.js用让
来运行你的例子的方式来运行在让
不可用的环境中:
This is how Babel.js translates your example with let
to run in environments where let
is not available:
"use strict";
(function timer() {
var _loop = function (i) {
setTimeout(function clog() {
console.log(i);
}, i * 1000);
};
for (var i = 0; i <= 5; i++) {
_loop(i);
}
})();
感谢 Michael Geary 在评论中发布了Babel.js的链接。请参阅评论中的链接以获取实时演示,您可以在其中更改代码中的任何内容并观看立即进行的翻译。看看其他ES6功能如何被翻译也很有趣。
Thanks to Michael Geary for posting the link to Babel.js in the comments. See the link in the comment for a live demo where you can change anything in the code and watch the translation taking place immediately. It's interesting to see how other ES6 features get translated as well.
这篇关于为什么让set和var绑定使用setTimeout函数表现不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!