[英]How does JavaScript pass-by-reference explain this behavior?
I am new to JavaScript, and recently stumbled across this problem questioning what would be printed to the console. 我是JavaScript的新手,最近偶然发现了该问题,询问将在控制台上打印什么。 The correct answer is
4 4 4 4
, because of pass-by-reference. 正确的答案是
4 4 4 4
,这是因为引用传递。 However, I don't understand how this is the result. 但是,我不知道结果如何。 Why does pass-by-reference dictate the output if the output is simply a value of
i
that seems only dependent upon an iteration of a for-loop
? 如果输出只是
i
的值(似乎仅取决于for-loop
的迭代),为什么按引用来决定输出?
const array = [10, 21, 31, 41];
for(i = 0; i < array.length; i++) {
setTimeout(function print(array){
console.log(i)}, 3000);
}
Okay, step by step: 好吧,一步一步来:
const array = [10, 21, 31, 41];
for(i = 0; i < array.length; i++) {
setTimeout(function print(array) { /* stuff... */ }, 3000);
}
// When we get to here, the value of i is 4.
When this snippet runs, we iterate the array, and set a timeout for each iteration. 当此代码段运行时,我们将迭代该数组,并为每次迭代设置一个超时。 When the for loop is finished, we have called
setTimeout
four times, but none of the functions given to setTimeout
have run. 当for循环完成时,我们已调用
setTimeout
四次,但没有运行给setTimeout
的函数。 Indeed, they won't run for another 3 seconds. 确实,它们不会再运行3秒钟了。
Most importantly, at this point, the value of i
is 4
. 最重要的是,此时
i
值为4
。
Three seconds later... 三秒钟后...
Finally, our function print
that we gave to setTimeout
is going to run. 最后,我们给
setTimeout
提供的函数print
将运行。 So what does that function look like?: 那么该函数是什么样的呢?
function print(array) { console.log(i); }
Now recall the value of i
is now 4. So it prints 4
, four times. 现在回想一下,
i
的值现在是4。因此它打印4
次,四次。 This is because it is when the function actually executes that it reads the value of the variable i
, not when the function was declared. 这是因为在函数实际执行时才读取变量
i
的值, 而不是在声明函数时。
Basically, i
is 4 at the time that your function print
is actually invoked, so therefore, it unsurprisingly prints 4
. 基本上,在实际调用函数
print
时, i
为4,因此,毫不奇怪,它打印4
。
Look again at the inner function which is being called by the timeout. 再次查看超时所调用的内部函数。
function print(array){
console.log(i);
}
At no point is the passed in array actually used for anything, in fact the following code will do exactly the same thing (print 4 4 4 4) 传入的数组在任何时候都不会真正用于任何事情,实际上,以下代码会做完全相同的事情(打印4 4 4 4)
for(i = 0; i < array.length; i++) {
setTimeout(function print(){
console.log(i)}, 3000);
}
The pass by reference part means that it isn't the value of i which is passed in to the print() function, but a reference to whatever value is held by i at the time console.log(i) is called. 通过引用传递部分意味着传递给print()函数的不是i的值,而是对i在调用console.log(i)时所保存的任何值的引用。 Since there is a 3 second delay, the loop has more than enough time to finish and the value of i is 4 by the time the first console.log(i) is called.
由于存在3秒的延迟,因此循环有足够的时间来完成,并且在调用第一个console.log(i)时,i的值为4。 You can even set the value of i after the loop and it will change the result.
您甚至可以在循环后设置i的值,它将改变结果。
for(i = 0; i < 4; i++) {
setTimeout(function print(){
console.log(i)}, 3000);
}
i = "foo";
// prints foo foo foo foo
您的setTimeout使您的代码异步,我们不再等待3000的超时,javascript循环在此之前结束,索引的最后一个值也是4。搜索“ js Eventloop”,您将发现更多关于浏览器简而言之。
There's only a single value of i
. i
只有一个值。 Calling setTimeout
doesn't store the original value anywhere. 调用
setTimeout
不会在任何地方存储原始值。
Because the print
function is called after the for-loop has finished running, the value of i
will be 4
because it's the value it'll have at the end of the for-loop. 因为
print
函数是在for循环完成运行之后调用的,所以i
的值为4
因为它是在for循环结束时使用的值。
To be able to use 'i' value you need something called closure. 为了能够使用“ i”值,您需要一种叫做闭包的东西。 When the function execute at that time i value became 4 and it gets printed.
当函数在那个时候执行时,我的值变成4并被打印。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.