Javascript 当分配给新变量时,循环内的计数器值会发生变化
我在学JS。为什么日志Javascript 当分配给新变量时,循环内的计数器值会发生变化,javascript,scope,Javascript,Scope,我在学JS。为什么日志funcs2[1]()日志4和funcs[1]()日志5 请注意,这不是的副本。我知道funcs[1]()记录5(而不是1),因为调用的函数绑定到i的当前值,循环终止时该值为5 但这不是我的问题。我想知道为什么funcs2[1]()日志4,而不是日志5 var funcs = []; for (var i = 0; i < 5; i++) { funcs.push(function () { return i; }); } conso
funcs2[1]()代码>日志4和funcs[1]()代码>日志5
请注意,这不是的副本。我知道funcs[1]()
记录5
(而不是1),因为调用的函数绑定到i
的当前值,循环终止时该值为5
但这不是我的问题。我想知道为什么funcs2[1]()代码>日志4,而不是日志5
var funcs = [];
for (var i = 0; i < 5; i++) {
funcs.push(function () {
return i;
});
}
console.log(funcs[1]());
5
var funcs2 = [];
for (var i = 0; i < 5; i++) {
var x = i;
funcs2.push(function () {
return x;
});
}
console.log(funcs2[1]());
4
var funcs=[];
对于(变量i=0;i<5;i++){
函数推送(函数(){
返回i;
});
}
console.log(funcs[1]());
5.
var funcs2=[];
对于(变量i=0;i<5;i++){
var x=i;
funcs2.push(函数(){
返回x;
});
}
console.log(funcs2[1]());
4.
因为当i增加到5时,它不会进入循环,所以最后x是4
这是一个著名的JS闭包问题,内部函数只将父上下文的变量对象保留在其内部[[scope]]
属性中,而不保留变量。因此,当循环完成时,父对象的VARABLE对象中的i
等于5,而x等于4。因为当i增加到5时,它不会进入循环,因此最终x等于4
这是一个著名的JS闭包问题,内部函数只将父上下文的变量对象保留在其内部[[scope]]
属性中,而不保留变量。因此,当循环完成时,父对象的VARABLE对象中的i
等于5,而x等于4。由于javascript中没有块作用域,在两个循环完成后,变量i
的值在这两种情况下都是5
然而,在第二种情况下,x
的值是4
,因为这是最后一个迭代索引,i++
发生在x=i
赋值之后。由于javascript中没有块范围,在两个循环完成执行后,变量i
的值在这两种情况下都是5
然而,在第二种情况下,x
的值是4
,因为这是最后一次迭代索引,i++
发生在x=i
赋值之后。对不起,我对原始帖子的编辑被拒绝。为了进一步讨论这一点,我用另一个案例作了另一个回答:
var funcs3 = [];
function foo() {
for (var k = 0; k < 5; k++) { // k is in foo's scope
funcs3.push(function () {
return k;
});
}
}
foo(); // k can't be accessed after from here
console.log(funcs3[1]()); // 5, k is still in closure
var funcs3=[];
函数foo(){
对于(var k=0;k<5;k++){//k在foo的范围内
funcs3.push(函数(){
返回k;
});
}
}
foo();//从这里以后无法访问k
console.log(funcs3[1]());//5,k仍处于关闭状态
对不起,我对原始帖子的编辑被拒绝。为了进一步讨论这一点,我用另一个案例作了另一个回答:
var funcs3 = [];
function foo() {
for (var k = 0; k < 5; k++) { // k is in foo's scope
funcs3.push(function () {
return k;
});
}
}
foo(); // k can't be accessed after from here
console.log(funcs3[1]()); // 5, k is still in closure
var funcs3=[];
函数foo(){
对于(var k=0;k<5;k++){//k在foo的范围内
funcs3.push(函数(){
返回k;
});
}
}
foo();//从这里以后无法访问k
console.log(funcs3[1]());//5,k仍处于关闭状态
所以最后一次计算i++
(i递增到5),循环体不执行,在funcs2中,由于我返回x,它会被固定在4?是的,i
总是最后一次递增,然后再次比较i<5
,但是当i
==5
时,您永远不会进入循环。放置console.log(x,i)代码>在var x=i
之后,您将看到。是的,我刚刚将i记录在funcs
的循环中,并发现它从未达到5。函数范围不是OP问题的根本原因,关闭机制是。因此上次对i++
进行了评估(i增加到5),循环体没有执行,在funcs2中,由于我返回x,它将被固定在4?是的,I
总是最后一次递增,然后再次比较I<5
,但是当I
==5
时,您永远不会进入循环。放置console.log(x,i)代码>在var x=i
之后,您将看到。是的,我刚刚将i记录在funcs
的循环中,发现它从未达到5。函数范围不是OP问题的根本原因,关闭机制是。谢谢。你的答案也是正确的,但是我选择了@ dfsq,因为它更好。不必介意,但我会考虑这是一个关闭问题,而不是函数/块范围问题。理解闭包是JS学习中的一条关键路径,我们正在谈论同样的事情。问题是因为没有块级别的作用域。因此,闭包的问题就出现了。如果
迭代的每个内部都有单独的作用域,则闭包中的值是正确的。@dfsq-实际上它们并不完全相同。看看我更新的funcs3案例,k
在foo
的范围内,似乎k
应该在foo
结束执行时被销毁,funcs3[1]
永远不能引用k
,但实际上funcs3[1]
通过闭包保留另一个对k
的引用,这样k
就不会被GCed。谢谢。你的答案也是正确的,但是我选择了@ dfsq,因为它更好。不必介意,但我会考虑这是一个关闭问题,而不是函数/块范围问题。理解闭包是JS学习中的一条关键路径,我们正在谈论同样的事情。问题是因为没有块级别的作用域。因此,闭包的问题就出现了。如果
迭代的每个内部都有单独的作用域,则闭包中的值是正确的。@dfsq-实际上它们并不完全相同。看看我更新的funcs3案例,k
在foo
的范围内,似乎k
应该在foo
结束执行时被销毁,funcs3[1]
永远不能引用k
,但实际上funcs3[1]
通过闭包保留对k
的另一个引用,以便k
不进行GCed。