JavaScript嵌套函数中的变量作用域 [英] Variable scope in nested functions in Javascript

查看:105
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆