3

下面的代码打印出来:

timedout false undefined

iethis不再指theActivityTimerin method timedOut()。我想知道为什么会这样。

var theActivityTimer = {
    timer: "",          
    active: false,       

    refresh: function () {
        theActivityTimer.timer = setTimeout(
            this.timedOut,
            5000     
        );
    },

    timedOut: function(){
        alert("timedout " +
            theActivityTimer.active + " " + this.active);
    }
}

theActivityTimer.refresh();

http://jsfiddle.net/spiderplant0/nQ4XX/

有没有办法告诉它可以使用this

4

3 回答 3

3

这个问题一直被问到;你会想要使用fn.bind

var theActivityTimer = {
    timer: null,          
    active: false,       

    refresh: function () {
        this.timer = setTimeout(this.timedOut.bind(this), 5000);
    },

    timedOut: function(){
        alert("timedout " + this.active);
    }
};

来自fn.bind文档

创建一个新函数,该函数在调用时将其this关键字设置为提供的值,并且在调用新函数时在任何提供的参数之前具有给定的参数序列。


免责声明:

fn.bind在 ECMAScript 5中实现。如果您在浏览器中使用它并且需要支持旧版本,请查看es5-shim


于 2013-09-04T17:30:11.307 回答
3

this取决于调用方法的方式。

foo.bar(); // this === foo

var bar = foo.bar();
bar() // this === window (defaults to global object)

setTimeout后者如此有效。

相反,通常传递一个匿名函数来维护对您的实例方法的正确调用。请记住,匿名函数也会丢失this,因此您需要将所保存的内容保存this到局部变量中,这也很常见。

var self = this;
theActivityTimer.timer = setTimeout(function() {
    self.timedOut()
}, 5000);

还有其他方法可以操作上下文( 的值this),但这种方法可能是最容易理解和最广泛支持的。

于 2013-09-04T17:31:06.563 回答
0

我想向该线程添加另一个解决方案以添加不需要任何额外工作或库并且是跨浏览器的内联解决方案。

var theActivityTimer = {
    timer: "",          
    active: false,       

    refresh: function () {
         theActivityTimer.timer = setTimeout(function() {
             theActivityTimer.timedOut();
         }, 5000);
    },
于 2013-09-04T17:52:41.440 回答