Javascript闭包函数不返回正确的值

时间:2013-01-31 21:42:53

标签: javascript closures return-value settimeout alert

我的Javascript代码有问题,不知道为什么它没有运行。

这是我的计时器:

var time = 0;
startTimer();

function startTimer(){
    setInterval(function(){
    time=time+1;
    },10);
}

此代码可以使用(我在点击按钮时运行timeoutTester(),然后它会提醒并显示时差):

function timeoutTester(){
    var snap_time1 = time;
    setTimeout(function(){
        var snap_time2 = time;
        var diff = snap_time2-snap_time1;
        alert(diff);            //works: ~100 everytime...
    },1000);
}

但是这里的代码不起作用(我通过点击按钮运行testTimer()):

function timeoutTester(){
    var snap_time1 = time;
    var result;
    setTimeout(function(){
        var snap_time2 = time;
        result = snap_time2-snap_time1;
    },1000);
    alert(result); //doesn't work! It always shows me: "undefined"
    return result;
}

function testTimer(){
    var counter = 0;
    setInterval(function(){
        counter = counter + 1;
        alert(counter);         //works: 1,2,3,....
        var result = timeoutTester();
        alert(result);  //doesn't work! It always shows me: "undefined"
    }, 3000);
}

你知道问题出在哪里吗? (在浏览器中调试时没有错误!)

更新

我学会了警报(结果);立即执行,而结果尚无价值。

但是因为我从外面调用timeoutTester(),所以我仍然需要这个函数的返回值!

有什么想法吗?

2 个答案:

答案 0 :(得分:4)

在您的上一个示例(不起作用的示例)中,调用setTimeout(function()...)不会立即执行该函数,但会立即返回。返回时,result仍未定义,因为该函数尚未执行。

出于同样的原因,上一个示例(在超时函数中调用了alert())可以正常工作,因为alert()的调用在result被赋值后发生。 / p>

如果由于某种原因您不想直接从超时函数中调用alert(),您可以将最后一个示例重写为:

function timeoutTester(){
    var snap_time1 = time;
    setTimeout(function(){
        var snap_time2 = time;
        alertResult(snap_time2-snap_time1);
    },1000);
}
function alertResult(result) {
    alert(result);
}

(顺便说一句,调用startTimer(1000000000000);看起来很可怕,直到我意识到这个论点被忽略了。: - )。)

答案 1 :(得分:1)

要完成此操作,您需要使用全局:

var timeoutTesterResult;

function timeoutTester(){
    var snap_time1 = time;
    var result;
    setTimeout(function(){
        var snap_time2 = time;
        timeoutTesterResult = snap_time2-snap_time1;
        alert(timeoutTesterResult);                    //works: ~100
    },1000);
}

第二次超时只有在设置/更改后才会获得全局:

function testTimer(){
    var counter = 0;
    setInterval(function(){
        counter = counter + 1;
        alert(counter);         //works: 1,2,3,....
        timeoutTester();
        setTimeout("alert(timeoutTesterResult)",1000); //works: ~100
    }, 3000);
}

这就是“通过全球化”解决方案。