为什么关闭行为不会在这里发挥作用:
function init(){
for (var i = 1; i <= 2; i++) {
function timer() {
var k=i;
console.log("in timer");
console.log(timer.i);
console.log(k);
}
timer.i = i;
setTimeout(timer, 0);
}
}
&#13;
<body onload="init()";>
</body>
&#13;
为什么timer.i没有在外部函数init的堆栈中取i的最后一个值?但是,它确实需要k的外部。
答案 0 :(得分:0)
EcmaScript 6中的函数声明现在是块作用域的,就像let
声明一样(与let
的区别在于变量在外部global / functionnal范围内声明)。
您的代码全局等同于
for (var i = 1; i <= 2; i++) {
let timer = function() {
console.log("in timer");
console.log(timer.i);
}
timer.i = i;
setTimeout(timer, 1000);
}
&#13;
这意味着您有不同的timer
值。
请注意,如果您使用的是var
而不是let
而不是函数声明,那么将获得两倍的相同日志。
好读:http://2ality.com/2015/02/es6-scoping.html
请注意,为函数添加属性并不是一个好习惯。您应该使用范围变量,例如:
for (var i = 1; i <= 2; i++) {
let timer_i = i;
setTimeout(function timer(){
console.log("in timer");
console.log(timer_i);
}, 1000);
}
在这个简单的情况下可以写成
for (let i = 1; i <= 2; i++) {
setTimeout(function timer(){
console.log("in timer");
console.log(i);
}, 1000);
}
答案 1 :(得分:0)
实际上有两个 timer
。当解释器在类似循环内的函数声明中运行时,它将覆盖外部作用域中的前一个函数名称(如果存在这样的函数)。这个片段可能会更清晰:
for (var i = 1; i <= 2; i++) {
const oldTimer = window.timer;
function timer() {
console.log("in timer");
console.log(timer.i);
}
timer.i = i;
console.log('oldTimer is ' + oldTimer + (oldTimer ? ' with i of ' + oldTimer.i : ''));
console.log('is oldTimer the same as the new timer? ' + (oldTimer === timer));
setTimeout(timer, 1000);
}
console.log('Outside of for loop: timer is ' + typeof timer);
&#13;
(timer
仍然可以在for
循环之外使用 - 它会被添加到全局对象中。)