use*_*820 45 javascript var let
此代码记录6
6次:
(function timer() {
for (var i=0; i<=5; i++) {
setTimeout(function clog() {console.log(i)}, i*1000);
}
})();
Run Code Online (Sandbox Code Playgroud)
但是这段代码......
(function timer() {
for (let i=0; i<=5; i++) {
setTimeout(function clog() {console.log(i)}, i*1000);
}
})();
Run Code Online (Sandbox Code Playgroud)
...记录以下结果:
0
1
2
3
4
5
Run Code Online (Sandbox Code Playgroud)
为什么?
是因为不同地let
绑定到内部范围每个项目并var
保持最新值i
?
rsp*_*rsp 43
有了var
你有一个功能范围,只有一个共享您的所有循环迭代的结合-即在i
每一个setTimeout的回调意味着相同的变量,最后是循环迭代结束后等于6.
与let
你有一个块的范围,并在使用时for
循环中,您得到每个迭代一个新的结合-即i
在每一个setTimeout的回调意味着不同的变量,每个都有不同的价值:第一个是0,下一个就是1等
所以这:
(function timer() {
for (let i = 0; i <= 5; i++) {
setTimeout(function clog() { console.log(i); }, i * 1000);
}
})();
Run Code Online (Sandbox Code Playgroud)
相当于仅使用var:
(function timer() {
for (var j = 0; j <= 5; j++) {
(function () {
var i = j;
setTimeout(function clog() { console.log(i); }, i * 1000);
}());
}
})();
Run Code Online (Sandbox Code Playgroud)
使用立即调用的函数表达式来使用函数作用域,其方式类似于块作用域在示例中的作用let
.
它可以在不使用j
名称的情况下编写得更短,但也许它不会那么清楚:
(function timer() {
for (var i = 0; i <= 5; i++) {
(function (i) {
setTimeout(function clog() { console.log(i); }, i * 1000);
}(i));
}
})();
Run Code Online (Sandbox Code Playgroud)
使用箭头功能更短:
(() => {
for (var i = 0; i <= 5; i++) {
(i => setTimeout(() => console.log(i), i * 1000))(i);
}
})();
Run Code Online (Sandbox Code Playgroud)
(但是如果你可以使用箭头功能,那就没有理由使用了var
.)
这就是Babel.js如何将您的示例转换let
为在let
不可用的环境中运行:
"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);
}
})();
Run Code Online (Sandbox Code Playgroud)
感谢Michael Geary在评论中发布了Babel.js的链接.请参阅评论中的链接以获取实时演示,您可以在其中更改代码中的任何内容并观看立即进行的翻译.看看其他ES6功能如何被翻译也很有趣.
从技术上讲,这就是@rsp在其出色答案中的解释方式。这就是我喜欢了解事物在幕后运作的方式。对于使用的第一段代码var
(function timer() {
for (var i=0; i<=5; i++) {
setTimeout(function clog() {console.log(i)}, i*1000);
}
})();
Run Code Online (Sandbox Code Playgroud)
您可以想象编译器在for循环中会像这样
setTimeout(function clog() {console.log(i)}, i*1000); // first iteration, remember to call clog with value i after 1 sec
setTimeout(function clog() {console.log(i)}, i*1000); // second iteration, remember to call clog with value i after 2 sec
setTimeout(function clog() {console.log(i)}, i*1000); // third iteration, remember to call clog with value i after 3 sec
Run Code Online (Sandbox Code Playgroud)
等等
由于i
使用调用var
时进行了声明clog
,因此编译器会i
在最近的功能块中找到变量,timer
并且由于我们已经到达for
循环的末尾,因此i
将值保存为6,然后执行clog
。这说明6被记录了六次。
归档时间: |
|
查看次数: |
7477 次 |
最近记录: |