Return 带 let 变量的循环内存储函数的值评估
Return value evaluation of a stored function inside a loop with let variable
据我了解,如果 for 循环的循环变量是用 var 定义的,那么对该变量的任何更改都会全局应用。例如:
var printNumTwo;
for (var i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
在上面的代码中,3 将打印到控制台中。因为在最后一次迭代中变量 i 将等于 3。因此当调用 printNumTwo 时,将返回更新 i。
但是,如果我使用 let 则情况并非如此,并且会发生以下行为:
let printNumTwo;
for (let i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
以上代码将打印 2.
let printNumTwo;
for (let i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
i = 3;
}
}
console.log(printNumTwo());
然而,上面的代码打印了 3。
这是什么原因?
however, the above code prints 3. What is the reason for this?
因为您将 3
分配给 i
变量,printNumTwo
关闭了。在创建 printNumTwo
之后发生赋值并不重要,只是它是 printNumTwo
正在使用的变量。
var
和 let
在 for
循环中的区别在于,为循环体创建了一个 new 变量每个循环迭代 let
。但是你在循环体内分配给那个变量,所以函数关闭 (printNumTwo
) 它稍后在你调用它时看到那个值。
完全是这样的:
function create(i) {
// This function closes over `i`
const fn = function() {
return i;
};
// This modifies the `i` it closes over
++i;
return fn;
}
const printValue1 = create(1);
console.log(printValue1()); // 2 (1 + 1)
const printValue27 = create(27);
console.log(printValue27()); // 28 (27 + 1)
在回答对该问题的评论时,您说:
same thing also happens in the second code block (i++ in the update section in for loop ) but the answer is 2
啊!现在我明白为什么会有误会了。你是对的 i
有更新——但 printNumTwo
关闭的不是 i
。
for
的更新部分在下一次迭代开始时对 new 变量执行,而不是在迭代的那个上执行刚刚在迭代结束时完成。它这样做:
- 创建一个新的迭代变量(我们称之为
iNew
)
- 将旧迭代变量(我们称它为
iOld
)的值赋给新变量(iNew = iOld
)
- 运行 更新代码使用
iNew
(iNew++
)
这就是为什么 i
(旧的)仍然 2
的原因;这是新的 3
.
在第一个示例中,var
作用域 i
到函数,因此在循环结束时 i++
将 i
从 2
更改为3
循环停止。 只有 i
现在是 3
和 printNumTwo
returns i
即 3
.
在第二个例子中,let
作用域 i
到块,因此分配给 printNumTwo
的函数关闭它。 last 循环主体运行的时间,i
是 2
和 printNumTwo
returns i
即 2
。 (使用值 3
创建了一个新的 i
,但没有创建使用它的函数)。
在第三个例子中,let
范围 i
到块,同样的事情发生了,除了你有 i = 3;
改变 every i
到 3
。所以最后创建的函数(以及之前被覆盖的函数)returns i
即 3
.
var的范围是函数,let的范围是块。
所以给printNumTwo
函数赋值的时候,i
的值还是2,跟后面的i
怎么样都没有关系。
var 和 let 的行为你可以从这个例子中理解。
for(var i=0; i<3; i++){
setTimeout(() => console.log('var', i))
}
for(let i=0; i < 3; i++){
setTimeout(() => console.log('let',i))
}
据我了解,如果 for 循环的循环变量是用 var 定义的,那么对该变量的任何更改都会全局应用。例如:
var printNumTwo;
for (var i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
在上面的代码中,3 将打印到控制台中。因为在最后一次迭代中变量 i 将等于 3。因此当调用 printNumTwo 时,将返回更新 i。 但是,如果我使用 let 则情况并非如此,并且会发生以下行为:
let printNumTwo;
for (let i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
以上代码将打印 2.
let printNumTwo;
for (let i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
i = 3;
}
}
console.log(printNumTwo());
然而,上面的代码打印了 3。 这是什么原因?
however, the above code prints 3. What is the reason for this?
因为您将 3
分配给 i
变量,printNumTwo
关闭了。在创建 printNumTwo
之后发生赋值并不重要,只是它是 printNumTwo
正在使用的变量。
var
和 let
在 for
循环中的区别在于,为循环体创建了一个 new 变量每个循环迭代 let
。但是你在循环体内分配给那个变量,所以函数关闭 (printNumTwo
) 它稍后在你调用它时看到那个值。
完全是这样的:
function create(i) {
// This function closes over `i`
const fn = function() {
return i;
};
// This modifies the `i` it closes over
++i;
return fn;
}
const printValue1 = create(1);
console.log(printValue1()); // 2 (1 + 1)
const printValue27 = create(27);
console.log(printValue27()); // 28 (27 + 1)
在回答对该问题的评论时,您说:
same thing also happens in the second code block (i++ in the update section in for loop ) but the answer is 2
啊!现在我明白为什么会有误会了。你是对的 i
有更新——但 printNumTwo
关闭的不是 i
。
for
的更新部分在下一次迭代开始时对 new 变量执行,而不是在迭代的那个上执行刚刚在迭代结束时完成。它这样做:
- 创建一个新的迭代变量(我们称之为
iNew
) - 将旧迭代变量(我们称它为
iOld
)的值赋给新变量(iNew = iOld
) - 运行 更新代码使用
iNew
(iNew++
)
这就是为什么 i
(旧的)仍然 2
的原因;这是新的 3
.
在第一个示例中,var
作用域 i
到函数,因此在循环结束时 i++
将 i
从 2
更改为3
循环停止。 只有 i
现在是 3
和 printNumTwo
returns i
即 3
.
在第二个例子中,let
作用域 i
到块,因此分配给 printNumTwo
的函数关闭它。 last 循环主体运行的时间,i
是 2
和 printNumTwo
returns i
即 2
。 (使用值 3
创建了一个新的 i
,但没有创建使用它的函数)。
在第三个例子中,let
范围 i
到块,同样的事情发生了,除了你有 i = 3;
改变 every i
到 3
。所以最后创建的函数(以及之前被覆盖的函数)returns i
即 3
.
var的范围是函数,let的范围是块。
所以给printNumTwo
函数赋值的时候,i
的值还是2,跟后面的i
怎么样都没有关系。
var 和 let 的行为你可以从这个例子中理解。
for(var i=0; i<3; i++){
setTimeout(() => console.log('var', i))
}
for(let i=0; i < 3; i++){
setTimeout(() => console.log('let',i))
}