emk*_*kay 2 javascript variables scope nested function
我查看了无数的例子,表明这应该有用,但事实并非如此.我想知道是否有人可以看一看并说明原因.我试图从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);
}
Run Code Online (Sandbox Code Playgroud)
T.J*_*der 11
有两个问题:
第一个是你传递到函数setTimeout有一个持久的引用的dia变量,不是一个副本的dia的价值作为创建功能时的感觉.因此,当功能运行时,他们都看到了相同的值dia,这是它的价值,然后,在循环完成后.
这个例子可能有助于使这更清楚:
var a = 1;
setTimeout(function() {
alert(a);
}, 0);
a = 2;
setTimeout(function() {
alert(a);
}, 0);
Run Code Online (Sandbox Code Playgroud)
上面的代码两次显示"2".它不会向我们显示"1"然后显示"2".这两个函数a在运行时都可以访问.
如果你考虑一下,这正是全局变量的工作原理.事实上,这是有原因的:它正是全局变量的工作方式.:-)
更多:关闭并不复杂
现在,有时,您希望获得dia创建函数时的值的副本.在这些情况下,您通常使用构建器函数并将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();
};
}
Run Code Online (Sandbox Code Playgroud)
因为函数buildFunction返回结束d,它不会改变,而不是改变dia,它会给我们创建时的值.
第二个问题是你的循环条件不正确,这就是你看到的原因undefined.你的循环是:
for(dcount = 0; dcount <= dialogue.length; dcount++) {
Run Code Online (Sandbox Code Playgroud)
没有任何元素dialogue[dialogue.length].最后一个元素是dialogue[dialogue.length - 1].你应该退出你的循环< dialogue.length,而不是<= dialogue.length.有了< dialogue.length,你仍然有一个问题:dia永远是最后一个条目(见上文),但至少它不会是未定义的.