Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.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_Variables_Scope - Fatal编程技术网

Javascript 可变全局范围理解问题

Javascript 可变全局范围理解问题,javascript,variables,scope,Javascript,Variables,Scope,我的问题实际上是理解——我有一个有效的解决方案,我只是不明白它是如何工作的 好的,我要做的是在循环中添加一个setTimeout,并通过它传递一个变化的值。例如: for (i=0;i<11;i++) { setTimeout("alert(i)",1000); } 用于(i=0;i此操作的作用: function(x){return function(){alert(x)};}(i) 它是否具有以下功能: function(x){ ...code... } 并立即执行它,

我的问题实际上是理解——我有一个有效的解决方案,我只是不明白它是如何工作的

好的,我要做的是在循环中添加一个setTimeout,并通过它传递一个变化的值。例如:

for (i=0;i<11;i++)
{
     setTimeout("alert(i)",1000);
}
用于(i=0;i此操作的作用:

function(x){return function(){alert(x)};}(i)
它是否具有以下功能:

function(x){ ...code... }
并立即执行它,将
i
(从
for
循环中)作为唯一的参数传入(这就是末尾的
(i)
的作用)。这将返回另一个函数:

function(){ alert(x); }

这就是传递给
setTimeout()的结果
作为计时器启动时调用的函数,它没有引用正在更改的循环中的变量
i
,而是使用创建新函数时传入的副本。

调用返回函数的函数的原因是,您需要某种方式将函数传递给
>setTimeout()
以引用当前值
i

由于代码等待运行1000毫秒,因此
for
循环将在运行之前完成,if
i
的值将为11

但由于函数有自己的变量作用域,因此可以将
i
的值传递到立即被调用的函数中,以便由局部变量
x
引用,当
setTimeout()
最终调用它时,返回的函数可以引用该局部变量

for (i=0; i<11; i++) {
    setTimeout(function(x){
                 // CONTINUE HERE:
                 // x is a local variable to the function being executed
                 //    which references the current value of i

                 // A function is being returned to the setTimeout that
                 //    references the local x variable
                 return function(){ alert(x); };

               }(i) // START HERE:
                    // The "outer" function is executed immediately, passing the
                    //   current value of "i" as the argument.
     ,1000);
}

Patrick和Nick在理解整个事情上帮了我很大的忙,所以我想为所有和我有同样问题的人总结一下:

setTimeout(以及其他一些延时函数,如eventlisteners)似乎将回调存储为字符串,然后对该字符串使用某种内部求值,从而将其解释为代码

这会导致循环和延时函数出现问题,因为它们对变量的引用引用引用了该循环的最终结果,或者可能是一个甚至不是全局的变量

据我所知,函数中的函数解决方案通过将字符串作为函数结果返回来解决此问题,该结果包含值,而不是变量的引用(
alert(“1”)
not
alert(I)

关于缩短代码,我简单的想法得出了一个简单的解决方案。由于回调应该是一个字符串,为什么不将变量值写入该字符串,然后返回:

for (i=0;i<11;i++)
{
     setTimeout("alert("+i+")",1000);
}

for(i=0;i+1表示“我真的很想理解我所有的代码,而不仅仅是使用我在某处找到的东西并很高兴它能工作”感谢nick花时间向我解释这一点,也感谢“+1”。事实上,我的所有页面(airports.palzkill.de)都是如此-除了谷歌的东西-是自制的。帕特里克,非常感谢。这可能是丢失的链接。马可-你部分正确。A
setTimeout
可以接受一个字符串作为参数,然后它将尝试
eval
。如果方法(如警报)存在于全局命名空间中,它将触发。但是
setTimeout
也可以接受函数对象作为参数。这是通过传递匿名函数来完成的(示例中的代码正在返回该函数),或通过将变量引用传递给函数。如果收到函数,则将在全局命名空间中调用它,而不管它是否起源于私有范围。在js中,您可以像这样传递函数。
setTimeout( function(){ alert(x); }, 1000); //...where x === 0
setTimeout( function(){ alert(x); }, 1000); //...where x === 1
setTimeout( function(){ alert(x); }, 1000); //...where x === 2
setTimeout( function(){ alert(x); }, 1000); //...where x === 3
// etc.
for (i=0;i<11;i++)
{
     setTimeout("alert("+i+")",1000);
}