[英]Variable scope in nested functions in Javascript
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:
我试图从setTimeout函数中访问变量“dia”,但它总是返回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);
}
There are two problems: 有两个问题:
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. 第一个是你传递给
setTimeout
的函数有一个对dia
变量的持久引用 , 而不是创建函数时dia
的值的副本 。 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. 因此,当功能运行时,他们都看到相同的值
dia
,这是它有那么值,循环完成后。
This example may help make this clearer: 这个例子可能有助于使这更清楚:
var a = 1;
setTimeout(function() {
alert(a);
}, 0);
a = 2;
setTimeout(function() {
alert(a);
}, 0);
The code above shows us "2" twice. 上面的代码两次显示“2”。 It does not show us "1" and then "2".
它不会向我们显示“1”然后显示“2”。 Both functions access
a
as it is when they run . 这两个函数访问
a
,因为它是它们运行时。
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.
事实上,这是有原因的:它正是全局变量的工作方式。 :-)
:-)
More: Closures are not complicated 更多: 关闭并不复杂
Now, sometimes, you want to get a copy of dia
's value as of when the function was created. 现在,有时候,你想要在创建函数时获得
dia
的值的副本。 In those cases, you usually use a builder function and pass dia
to it as an argument. 在这些情况下,您通常使用构建器函数并将
dia
作为参数传递给它。 The builder function creates a function that closes over the argument , rather than dia
: 构建器函数创建一个关闭参数的函数 ,而不是
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();
};
}
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. 因为函数
buildFunction
返回关闭d
,它不会改变,而不是dia
,它确实给出了它在创建时的值。
The second problem is that your loop condition is incorrect, which is why you're seeing undefined
. 第二个问题是你的循环条件不正确,这就是你看到
undefined
。 Your loop is: 你的循环是:
for(dcount = 0; dcount <= dialogue.length; dcount++) {
There is no element at dialogue[dialogue.length]
. dialogue[dialogue.length]
没有元素dialogue[dialogue.length]
。 The last element is at dialogue[dialogue.length - 1]
. 最后一个元素是
dialogue[dialogue.length - 1]
。 You should be exiting your loop with < dialogue.length
, not <= dialogue.length
. 您应该使用
< dialogue.length
,而不是<= dialogue.length
dialog.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. 使用
< dialogue.length
,你仍然有一个问题: dia
总是最后一个条目(见上文),但至少它不会是未定义的。
try this 尝试这个
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(count) {
alert(dialogue[count]);
}, loopDelay,dcount);
}
This solution just pass an argument to the setTimeout function so it can take the array index from there and take the correct item 这个解决方案只是将参数传递给setTimeout函数,因此它可以从那里获取数组索引并获取正确的项
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.