为什么需要一个匿名函数来保存"这个"使用setTimeout

时间:2014-01-29 11:08:46

标签: javascript settimeout

我多次使用setTimeout传递一个函数作为参考,例如

setTimeout(someFunction, 3000);

在某些情况下,要保留this的值,我必须事先将其分配给变量,但不明白为什么以下内容不起作用:

var logger = {
    log: function() { 
        var that = this;
        console.log(that.msg); 
        setTimeout(that.log, 3000); 
    },
    msg: "test"
};

logger.log();

然而,使用匿名函数确实有效:

var logger = {
    log: function() { 
        var that = this;
        console.log(that.msg); 
        setTimeout(function() { that.log() }, 3000); 
    },
    msg: "test"
};

2 个答案:

答案 0 :(得分:5)

这不起作用setTimeout调用一个this值作为全局对象而不是父对象的函数。您已将值传递到setTimeout函数 - 它不知道它是如何被访问的,因此无法使用正确的this值调用它(不像正常变量,this的值仅在您调用函数时确定,除非使用thisFunction.prototype.bind绑定到特定值。

通过将其更改为匿名函数,您可以使用闭包来访问that的值,即使在作为值调用时(函数的变量范围在定义时设置,不是什么时候运行。)

就像你做这样的事情一样:

var a = { b: function () { return this.foo; }, foo: 'proper' };
function test(arg) {
    return arg();
}
var foo = 'random';
console.log(a.b()); // proper
console.log(test(a.b)); // random

还有一个与this setTimeout {{1}}一起使用的相关问题:Pass correct "this" context to setTimeout callback?

答案 1 :(得分:2)

因为在第一种情况下,您只引用log对象中的函数that,但它与that的关系丢失了。可以认为它是setTimeout直接使用全局上下文在存储的内存地址调用log方法。

在第二个示例中,您来自全局上下文,但是先查找that,然后查找log,然后调用that的上下文。

认为setTimeout具有以下结构:

var setTimeout = function (func, time) {
   someWaitMechanism(time, function () { //this is called after the timeout
       func.call(null); //calls func with global scope
   });
}