【问题标题】:Why is the wrong object removed?为什么删除了错误的对象?
【发布时间】:2013-07-10 09:21:48
【问题描述】:

我编写了这个简单的类来创建一个带有消息的 div 元素,该消息应该在给定时间后消失。这很好用,但是当使用它创建多条消息时,隐藏和销毁功能将仅适用于最后创建的消息。

这是我的课:

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);

可能有一些参考错误,但我没有发现任何错误。

【问题讨论】:

  • 在您的代码中包含jsfiddle 会很有用。
  • this inside setTimeout 可能不是你想的那样......
  • 你有var self = this 来避免嵌套函数没有正确this 的问题(这很好),但是你不使用self 几乎只要你需要。也就是说:你有大量的this 用法实际上是指window。因此,您的所有函数都在 window.obj 上运行,而不是在特定于实例的 obj 字段上运行。
  • 这是一个有效的小提琴:jsfiddle.net/Dkf89
  • 关于self,你可以说self.display();,你不需要使用.call()来做self.display.call(this);(即使this是你当时所期望的,它不是)。

标签: javascript class dom object reference


【解决方案1】:

您已经非常接近可行的解决方案了。我在这里修复了代码: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);

【讨论】:

  • 代替:self.display.call(self); 只需:self.display();。那里真的不需要.call()
  • 非常正确。已修复(在移动设备上...希望已修复)
【解决方案2】:

我相信这些this'es 会变成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);
}

(我想我都得到了它们......如果我也错过了一个地方,请告诉我)

【讨论】:

  • 这是一个好的开始,但是这些方法需要更改为在self 而不是它们的this 上运行。
  • 在您的第二个代码块中,这些:setTimeout(self.display, 20); 将有相同的this 问题。
  • 关于您的更新,这几乎可以工作,但您忘记添加 () 来调用函数。
【解决方案3】:

也许你可以试试这个作为解决方案。去掉init函数,把你里面的this改成setTimeouts为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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    • 2018-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多