How am getting this output ? Javascript ES6
请在这里找到我的代码段,
1 2 3
| for (var i=0;i<11;i++) {
setTimeout( () => console.log(i), 10);
} |
如何打印11 11次? 因为i设定为<11?
如果我没有功能它控制它打印1-10。
1 2 3
| for (var i=0;i<11;i++) {
setTimeout( console.log(i), 10);
} |
这给了我1-10。 我很奇怪如果我包括没有条件的功能它会如何改变?
-
只有一个i,当计时器触发时它的值是11。
-
为了扩展@Pointy所说的,setTimeout是一个异步函数,所以当第一个日志发生时,for循环已经完成运行(它执行i++直到i<11为false,并且第一次发生的时候是i === 11)
-
因为变量是引用?
-
@PatrickBarr,它解释了为什么它开始打印1.如果没有setTimeout()那么它将打印0..10,而不是1..11。
-
@Darkrum:在这种情况下不是这样,因为i是一个数字。发生的事情是函数创建闭包。随附i。
-
@manassehkatz:它不会以1开始打印。它以11开始打印。它打印11,11,11 ...十次
-
@slebetman我在1-10的问题中看到了一个提及。取决于时间,它几乎可以是任何东西 - 除了"正常"0..10。
-
也没人提到第二个会打印数字而不等待,setTimeout会收到调用console.log的结果
-
@manassehkatz:这个具体的例子不依赖于时间,也不是什么。这是11,11,11 ......
根案例:
1 2 3
| for (var i=0;i<11;i++) {
setTimeout( console.log(i), 10);
} |
console.log将直接触发(没有任何延迟),因此它应该是:
1 2 3
| for (var i=0;i<11;i++) {
setTimeout(function () { console.log(i); }, 10);
} |
这将直接给出与ES6相同的结果
正确的方法是使用闭包:
1 2 3 4 5
| for (var i=0;i<11;i++) {
((i) => {
setTimeout(() => console.log(i), 10);
})(i);
} |
我们在JavaScript中使用单线程模型的原因。因此,所有setTimeout将在for -cycle之后执行。
另外它可以用let:
1 2 3
| for (let i=1; i<=11; i++) {
setTimeout(() => console.log(i), 10);
} |
-
鉴于问题明确要求ES6,这不是解决方案。
-
Hm ... setTimeout( console.log(i), 10); - console.log将在setTimeout之外执行。情况就是这样......
-
我已经更新了答案
-
不,那不是我的意思。我的意思是你不应该使用IIFE来在ES6中引入范围。
-
@Bergi,在那种情况下你会建议什么?这是相当普遍的解决方案:github.com/getify/You-Dont-Know-JS/blob/master/…
-
查看链接的副本。
-
"通过使用闭包"这不是解决方案工作的原因。它起作用的原因是您通过调用函数创建新范围。该函数是否为闭包是无关紧要的。您传递给setTimeout的函数也是一个闭包,但如果没有IIFE,则不会产生所需的结果。所以说"使用封闭来解决这个问题"是不正确的。
1 2 3
| for (var i=0;i<11;i++) {
setTimeout( () => console.log(i), 10);
} |
为我做参考
推送堆栈超时
我++
推送堆栈超时
我++
...当执行for循环后,js有自由主"线程"
推送超时后10 ms,当主"线程"空闲时 - 将第一个超时推送到主"线程",引用变量的值为11,因为完成了循环。每次超时都这样做。
预期的输出可以通过以下方式存档:
1 2 3 4
| for (var i=0;i<11;i++) {
const num = i;
setTimeout(() => console.log(num), 10);
} |
Const num将i的值存储到执行时。之后它被垃圾收集。
-
你试过执行吗?)检查最后一个号码。
-
非常好。它正在返回堆栈。您可以在超时前执行null &&
-
你在循环的每次迭代中立即调用console.log并将其返回值传递给setTimeout,这将是未定义的。不要延迟对console.log的调用。尝试将setTimeout延迟增加到像10000这样的更大的延迟,你会看到它没有延迟任何东西。
-
@JonathanKuhn对!为失误抱歉。固定
-
@DanielMizerski,检查执行:i64.tinypic.com/forrp.png
-
@FieryCat问题是什么?记录的33和44不是来自console.log,它可能是最后一次setTimeout调用的内部id(来自setTimeout的返回值)。在控制台中运行代码时,它会自动记录上次调用函数的返回值。除此之外,它看起来非常好。