创建javascript子类型的实例会产生意外行为

时间:2012-07-22 16:20:39

标签: javascript inheritance

标题有点模糊,但老实说,如果不理解这个问题的解决方案,我就无法更好地定义它。

情况

我正试图用javascript来包围原型和继承。 用例是单个基本类型“A”。还有一个子类型'B'。 以下是演示此问题的最简单代码示例。 可以看到工作版here

<!DOCTYPE html>
<html>
 <head>
  <script type="text/javascript">
    function A () {
        this.node = document.createElement('div');
        this.node.innerHTML = 'A';
    }

    A.prototype.show = function () {
        document.body.appendChild(this.node);
    }

    function B () {
        this.node.innerHTML = 'B';
    }

    B.prototype = new A();
    B.prototype.constructor = B;

    function make_a () {
        (new A()).show();
    }

    function make_b () {
        (new B()).show();
    }
  </script>
 </head>
 <body>
  <button onclick="make_a()">Make A</button>
  <button onclick="make_b()">Make B</button>
 </body>
</html>

问题

  • 点击第一个按钮可以完成我的预期:它会在每次点击时创建一个新的“A”实例并将其添加到DOM中。
  • 但是,对第二个按钮执行相同操作时,只会向DOM添加一个“B”实例并将其保留在该实例中。无论点击多少次。
  • 如果您在此之后点击“A”,则会再次按预期创建新的“A”。
  • 再次单击第二个按钮,只需将现有的“B”节点移动到节点列表中的最后一个位置。

为什么make_b()的行为与make_a()的行为方式不同?

一些注意事项:

正在测试的浏览器是Chromium 20+和Firefox 13 +。

2 个答案:

答案 0 :(得分:1)

您必须在A构造函数中调用B构造函数:

function B () {
    A.call(this);
    this.node.innerHTML = 'B';
}

这是小提琴:http://jsfiddle.net/QUnDK/

答案 1 :(得分:1)

解释:

修改时

A.prototype.show = function () {
    document.body.appendChild(this.node);
    document.body.appendChild(this.node);
}

可以看到,具有相同节点参数的appendChild的多次调用不会导致多个appendend子项。

修改时

function B () {
    this.node.innerHTML = Math.random() > 0.5 ? "B":"C";
}

可以看到函数B覆盖了最后插入的子节点(通过A)。 (B()本身不会创建div)。

通过指令B.prototype = new A();在页面加载时调用函数A();每当按下按钮A时。 因此,在激活按钮B之前,始终会有最新创建的div子项。附加了最新创建的div 每当调用show()时,即对按钮点击的反应,对文档。

函数B()不会创建新的div节点,因此B()使用由A()创建/附加的最新子节点插入“B”。