JavaScript嵌套函数中的变量作用域 [英] Variable scope in nested functions in Javascript
问题描述
我浏览了无数示例,这些示例表明这应该起作用,但事实并非如此.我想知道是否有人可以看看并指出原因.我正在尝试从setTimeout函数中访问变量"dia",但它始终返回undefined:
I have looked through countless examples which indicate that this is supposed to work, but it does not. I was wondering if someone could have a look and indicate why. I am trying to access the variable "dia" from within the setTimeout function, but it always returns undefined:
var dialogue = new Array();
dialogue[0] = 'Hi there Mo, I am Mark. I will be guiding through the game for you today';
dialogue[1] = 'Hey there Mark, how you doing?';
dialogue[2] = 'I am doing fine sweetie pie, how about yourself?';
dialogue[3] = 'I am good too, thanks. Are you ready for today, i.e. the big day?';
dialogue[4] = 'I certainly am, Mark';
var dcount;
var loopDelay;
var diatext;
for(dcount = 0; dcount <= dialogue.length; dcount++) {
var dia = dialogue[dcount];
if(dcount == 0) { loopDelay = 0; } else {
loopDelay = ((dia.length)*1000)/18;
}
setTimeout(function() {
alert(dia);
diatext = Crafty.e('2D, DOM, Text')
.text(dia)
.textFont({ size: '11px', weight: 'bold' })
.attr({ x: 200, y: 150, w:400, h:300})
.css();
}, loopDelay);
}
推荐答案
有两个问题:
首先,要传递给setTimeout
的函数具有对dia
变量的持久引用,而不是一个副本函数创建时的dia
值的em>.因此,当函数运行时,它们在循环完成后都看到dia
的相同值,即它具有 then 的值.
The first is that the function you're passing into setTimeout
has an enduring reference to the dia
variable, not a copy of dia
's value as of when the function was created. So when the functions run, they all see the same value for dia
, which is the value it has then, after the loop is complete.
此示例可能有助于使这一点更清楚:
This example may help make this clearer:
var a = 1;
setTimeout(function() {
alert(a);
}, 0);
a = 2;
setTimeout(function() {
alert(a);
}, 0);
上面的代码两次向我们显示"2".它不会显示"1",然后显示"2".这两个函数都可以在运行 时直接访问a
.
The code above shows us "2" twice. It does not show us "1" and then "2". Both functions access a
as it is when they run.
如果您考虑一下,这正是全局变量的工作方式.实际上,这是有原因的:这正是全局变量的工作方式. :-)
If you think about it, this is exactly how global variables work. And in fact, there's a reason for that: It's exactly the way global variables work. :-)
更多: 关闭并不复杂
现在,有时您希望获得创建函数时dia
值的副本.在这些情况下,通常使用构建器函数并将dia
作为参数传递给它. builder函数创建一个关闭 argument 而不是dia
:
Now, sometimes, you want to get a copy of dia
's value as of when the function was created. In those cases, you usually use a builder function and pass dia
to it as an argument. The builder function creates a function that closes over the argument, rather than dia
:
for(dcount = 0; dcount <= dialogue.length; dcount++) { // But see note below about <=
var dia = dialogue[dcount];
if(dcount == 0) { loopDelay = 0; } else {
loopDelay = ((dia.length)*1000)/18;
}
setTimeout(buildFunction(dia), loopDelay);
}
function buildFunction(d) {
return function(d) {
alert(d);
diatext = Crafty.e('2D, DOM, Text')
.text(d)
.textFont({ size: '11px', weight: 'bold' })
.attr({ x: 200, y: 150, w:400, h:300})
.css();
};
}
由于函数buildFunction
返回的值不会更改d
的值,而是返回dia
的值,而d
的值不变.
Because the function buildFunction
returns closes over d
, which doesn't change, rather than dia
, which does, it gives us the value as of when it was created.
第二个问题是循环条件不正确,这就是为什么看到undefined
的原因.您的循环是:
The second problem is that your loop condition is incorrect, which is why you're seeing undefined
. Your loop is:
for(dcount = 0; dcount <= dialogue.length; dcount++) {
在dialogue[dialogue.length]
处没有任何元素.最后一个元素在dialogue[dialogue.length - 1]
.您应该使用< dialogue.length
而不是<= dialogue.length
退出循环.使用< dialogue.length
时,您仍然会遇到问题:dia
始终是最后一个条目(请参见上文),但至少不会是未定义的.
There is no element at dialogue[dialogue.length]
. The last element is at dialogue[dialogue.length - 1]
. You should be exiting your loop with < dialogue.length
, not <= dialogue.length
. With < dialogue.length
, you'd still have a problem: dia
would always be the last entry (see above), but at least it wouldn't be undefined.
这篇关于JavaScript嵌套函数中的变量作用域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!