Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/426.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript函数范围[Javascript Essentials]_Javascript_Arrays_Function_For Loop_Anonymous Function - Fatal编程技术网

Javascript函数范围[Javascript Essentials]

Javascript函数范围[Javascript Essentials],javascript,arrays,function,for-loop,anonymous-function,Javascript,Arrays,Function,For Loop,Anonymous Function,我在看Travis Tidwell的Javascript Essentials,他解释了这段代码: (function() { var messages = ['hello', 'there']; for (var i in messages) { setTimeout(function() { console.log(messages[i]); }, 10); }; })(); 它在控制台中重复“there”

我在看Travis Tidwell的Javascript Essentials,他解释了这段代码:

(function() {
    var messages = ['hello', 'there'];

    for (var i in messages) {
        setTimeout(function() {
            console.log(messages[i]);
        }, 10); 
    };
})();

它在控制台中重复“there”两次,但我仍然不明白确切的原因。有人能和我一起一步一步地看一下这段javascript吗?

每次代码循环时,它都会设置一个事件处理程序,以便在经过10毫秒后,它会记录
消息[i]
的值

在这些超时超过10毫秒之前,
i
的值已更改(通过
for
循环)为
1
(因为这是数组中最后的属性名称)

第一次超时输出
消息[1]
,然后第二次超时输出
消息[1]


  • 数组被创建并存储在
    消息中
  • i
    设置为
    0
    并设置超时
  • i
    设置为
    1
    ,并设置超时
  • 第一个超时函数运行时,
    i
    仍然是
    1
  • 第二个超时函数运行时,
    i
    仍然是
    1

  • JavaScript具有函数作用域,而不像其他语言那样具有块作用域。因此,实际上只存在一个
    i
    变量。调用
    setTimeout
    中的代码时,
    i
    已设置为数组的最后一个索引

    很快,在ECMAScript 6中,我们可以使用
    let
    声明块作用域变量。请看这里:

    在此之前,解决此行为的方法之一是为需要独立于其他变量的变量创建新函数:

    (函数(){
    var messages=['hello','there'];
    for(消息中的var i){
    (功能(当前索引){
    setTimeout(函数(){
    logToOutput(消息[currentIndex]);
    }, 10);
    })(i) );
    };
    })();
    函数logToOutput(msg){
    document.getElementById(“输出”).innerHTML+=msg+“
    ”; }

    请参阅:这是臭名昭著的
    循环内闭包问题。如果你搜索这个,你会发现大量的信息。本质上,这种行为的原因是for循环在超时触发时已经完成。此时,
    i
    具有最后一个循环的值,用于两个超时。如果将“10”替换为“0”,为什么行为相同?@johnnyRose浏览器施加的最小超时值通常超过10毫秒。因为(a)强制执行最小超时,并且(b)JavaScript是单线程的,事件循环不寻找在运行另一个函数的过程中要处理的事件。@ J.NynRoSE作为概念证明来显示其他评论者所说的内容,请参见。打开控制台,看到在“there”消息之前有两条“loop iteration”消息…“但设置超时时,它没有存储i[0]计数,这真的很奇怪”-不,它没有。这是JavaScript的一个基本特性。创建函数不会立即创建每个变量的本地范围副本并冻结其值。该函数在使用前甚至不会查看
    i