24

为什么我不能setTimeout在 javascript 对象中使用?

Message = function () {

    ...
    ...        

    this.messageFactory = ...
    this.feedbackTag = document.getElementById('feedbackMessages');

    this.addInfo = function (message) {
        var info = this.messageFactory.createInfo(message); // create a div
        this.feedbackTag.appendChild(info);

        setTimeout('this.feedbackTag.removeChild(info)', 5000);
        // why in here, it complain this.feedbacktag is undefined ??????

    };
}

感谢史蒂夫的解决方案,如果代码如下所示,现在它将起作用......因为之前的“this”实际上指向 setTimeOut 中的函数,它无法搜索 Message。

Message = function () {

    ...
    ...        

    this.messageFactory = ...
    this.feedbackTag = document.getElementById('feedbackMessages');

    this.addInfo = function (message) {
        var info = this.messageFactory.createInfo(message); // create a div
        this.feedbackTag.appendChild(info);

        var _this = this;
        setTimeout(function() { _this.feedbackTag.removeChild(info); }, 5000);

    };
}

但是,如果我们这样做,为什么它不起作用:

Message = function () {

    ...
    ...        

    this.messageFactory = ...
    this.feedbackTag = document.getElementById('feedbackMessages');
    // public function
    this.addInfo = function (message) {
        var info = this.messageFactory.createInfo(message); // create a div
        this.feedbackTag.appendChild(info);

        delayRemove(info);

    };
    // private function
    function delayRemove(obj) {
        var _this = this;
        setTimeout(function() { _this.feedbackTag.removeChild(info); }, 5000);
    }
}
4

3 回答 3

84

尝试替换此行:

setTimeout('this.feedbackTag.removeChild(info)', 5000);

用这两行:

var _this = this;
setTimeout(function() { _this.feedbackTag.removeChild(info); }, 5000);

笔记:

永远不要传递setTimeout一个字符串,因为这会调用eval(你应该只在必要时使用它)。相反,传递setTimeout一个函数引用(这可以是一个匿名函数)。

最后,始终检查this关键字是否指向您认为它指向的内容(请参阅http://www.alistapart.com/articles/getoutbindingsituations)。

解决问题 2:

我相信对于普通函数,this设置为window对象——不管它们在哪里声明。因此,将代码移动到单独的函数中并不能解决问题。

于 2009-07-09T03:39:06.853 回答
9

一种更简洁的方法是将作为参数传递给超时调用的函数:

function delayRemove(obj) {
  setTimeout(function(_this) {
      _this.feedbackTag.removeChild(obj);
    }, 5000, this);
}

你真的应该将obj作为参数传递,只是为了确保它在范围内(参数的数量是无限的):

function delayRemove(obj) {
  setTimeout(function(_this, removeObj) {
      _this.feedbackTag.removeChild(removeObj);
    }, 5000, this, obj);
}

HTML5 和 Node.js 扩展了setTimeout函数以接受传递给回调函数的参数。它具有以下方法签名。

setTimeout(callback, delay, [param1, param2, ...])

由于setTimeout 它实际上不是 JavaScript 功能,因此您的结果可能因浏览器而异。我找不到任何具体的支持细节,但正如我所说,这是在 HTML5 规范中。

于 2011-03-16T20:40:22.007 回答
2

要回答您的最后一个问题:“如果我们这样做,为什么它不起作用”:

Message = function () {

...
...        

this.messageFactory = ...
this.feedbackTag = document.getElementById('feedbackMessages');
// public function
this.addInfo = function (message) {
    var info = this.messageFactory.createInfo(message); // create a div
    this.feedbackTag.appendChild(info);

    delayRemove(info);

};
// private function
function delayRemove(obj) {
    var _this = this;
    setTimeout(function() { _this.feedbackTag.removeChild(info); }, 5000);
}}

它不起作用,因为您传递的是未定义的变量 ( info) 而不是已定义的变量 ( obj)。这是修正后的函数:

function delayRemove(obj) {
var _this = this;
setTimeout(function() { _this.feedbackTag.removeChild(obj); }, 5000);}
于 2010-12-01T14:29:35.933 回答