为什么删除了错误的对象?

时间:2013-07-11 22:30:22

标签: javascript class dom object reference

我已经编写了这个简单的类来创建一个带有消息的div元素,该消息应该在给定时间后消失。这很好用,但是当用这个创建多个消息时,hide和destroy函数将仅适用于最后创建的消息。

这是我的班级:

function message(text, duration){
    var self = this;

    function init(){
        this.obj = document.createElement("div");
        this.obj.setAttribute("class", "message");
        this.obj.appendChild(document.createTextNode(text));
        document.body.appendChild(this.obj);
        setTimeout(function(){self.display.call(this);}, 20);
        setTimeout(function(){self.hide.call(this);}, duration);
        setTimeout(function(){self.destroy.call(this);}, duration+1000);
    }

    this.display = function(){
        this.obj.setAttribute("class", "message display");
    }

    this.hide = function(){
        this.obj.setAttribute("class", "message gone");
    }

    this.destroy = function(){
        document.body.removeChild(this.obj);
    }

    init();
}

这有效:

new message("This will be removed in 5 seconds.", 5000);

这不应该有效:

new message("This will not be shown", 2000);
new message("This will be removed after 2 seconds", 5000);

可能存在一些参考错误,但我无法发现任何错误。

3 个答案:

答案 0 :(得分:2)

你非常接近一个有效的解决方案。我在这里修改了代码:http://jsfiddle.net/GTpKV/

您(正确)对此self进行了引用,但在您的代码中仍使用thisthis在使用内部函数时丢失,并且您还直接调用init,意味着this在这种情况下会引用window。如果你使用this.init()它会在对象上正确创建引用,但是超时会使事情搞乱。最安全的方式(我已采取)是简单地用this替换所有出现的self。另一个想法是分析上下文何时是正确的,何时不是。但是,由于您已经在self中拥有了正确绑定的上下文,因此您也可以使用它。以下是JSFiddle链接中的更正代码:

function message(text, duration){
    var self = this;

    function init(){
        self.obj = document.createElement("div");
        self.obj.setAttribute("class", "message");
        self.obj.appendChild(document.createTextNode(text));
        document.body.appendChild(self.obj);
        setTimeout(function(){self.display();}, 20);
        setTimeout(function(){self.hide();}, duration);
        setTimeout(function(){self.destroy();}, duration+1000);
    }

    this.display = function(){
        self.obj.setAttribute("class", "message display");
    }

    this.hide = function(){
        self.obj.setAttribute("class", "message gone");
    }

    this.destroy = function(){
        document.body.removeChild(self.obj);
    }

    init();
}

new message("This will not be shown", 2000);
new message("This will be removed in 5 seconds.", 5000);

答案 1 :(得分:1)

我相信这些this会成为window

setTimeout(function(){self.display.call(this);}, 20);
setTimeout(function(){self.hide.call(this);}, duration);
setTimeout(function(){self.destroy.call(this);}, duration+1000);

请尝试:

setTimeout(function(){self.display()}, 20);
setTimeout(function(){self.hide()}, duration);
setTimeout(function(){self.destroy()}, duration+1000);

另外,为什么不在代码的其余部分使用self

function init(){
    self.obj = document.createElement("div");
    self.obj.setAttribute("class", "message");
    self.obj.appendChild(document.createTextNode(text));
    document.body.appendChild(self.obj);
    setTimeout(function(){self.display()}, 20);
    setTimeout(function(){self.hide()}, duration);
    setTimeout(function(){self.destroy()}, duration+1000);
}

this.display = function(){
    self.obj.setAttribute("class", "message display");
}

this.hide = function(){
    self.obj.setAttribute("class", "message gone");
}

this.destroy = function(){
    document.body.removeChild(self.obj);
}

(我想我得到了所有这些......如果我也错过了一个地方,请告诉我)

答案 2 :(得分:0)

也许你可以尝试这个解决方案。摆脱init功能并将this内的setTimeout更改为self,并取消不必要的call

的Javascript

function message(text, duration) {
    var self = this;

    this.display = function () {
        this.obj.setAttribute("class", "message display");
    }

    this.hide = function () {
        this.obj.setAttribute("class", "message gone");
    }

    this.destroy = function () {
        document.body.removeChild(this.obj);
    }

    this.obj = document.createElement("div");
    this.obj.setAttribute("class", "message");
    this.obj.appendChild(document.createTextNode(text));
    document.body.appendChild(this.obj);
    setTimeout(function () {
        self.display(self);
    }, 20);
    setTimeout(function () {
        self.hide(self);
    }, duration);
    setTimeout(function () {
        self.destroy(self);
    }, duration + 1000);
}

new message("This will not be shown", 2000);
new message("This will be removed after 2 seconds", 5000);

jsfiddle