【问题标题】:Inheritance using prototype / "new" [duplicate]使用原型/“新”继承[重复]
【发布时间】:2011-01-06 07:03:15
【问题描述】:

您好,我是 Javascript OO 的新手,想了解有关继承的更多信息。希望大家多多指教!

我看到了这篇很棒的帖子: How to "properly" create a custom object in JavaScript?

它谈到了我在其他网站上看到的类是如何继承的,例如:

function man(x) {
    this.x = x;
    this.y = 2;
}
man.prototype.name = "man";
man.prototype.two = function() {
    this.y = "two";
}
function shawn() {
    man.apply(this, arguments);
};
shawn.prototype = new man;

上面的帖子声称,为了在继承时不调用“man”的构造函数,可以使用这样的帮助器:

function subclassOf(base) {
    _subclassOf.prototype= base.prototype;
    return new _subclassOf();
}
function _subclassOf() {};
shawn.prototype = subclassOf(man);

虽然我理解它的意图,但我不明白为什么我们不能打电话

shawn.prototype = man.prototype;

我看到它的工作原理完全相同。还是我缺少什么?提前致谢!

【问题讨论】:

    标签: javascript oop


    【解决方案1】:

    嗯,在我的拙见中,例子胜于言语。以下所有示例均使用您的代码,并添加了一些内容。

    第一个例子将证明使用shawn.prototype = new man; 你调用了两次构造函数

    function man(h, w) {
        SendMessage("man is created with height " + h + " and weight " + w);
        this.height = h;
        this.weight = w;
    }
    man.prototype.name = "man";
    man.prototype.double = function() {
        this.height *= 2;
        this.weigth *= 2;
    }
    function shawn() {
        man.apply(this, arguments);
    };
    
    function SendMessage(msg) {
        document.getElementById("Console").innerHTML += msg + "<br />";
    }
    
    window.onload = function() {
        shawn.prototype = new man;
        
        var p = new shawn(180, 90);
        SendMessage("Shawn height: " + p.height);
    }
    &lt;div id="Console"&gt;&lt;/div&gt;

    如您所见,构造函数被调用了两次 - 一次没有参数,然后使用您给它的实际参数。

    第二个例子只是证明使用subclassOf 解决了“双重调用”问题。

    function man(h, w) {
        SendMessage("man is created with height " + h + " and weight " + w);
        this.height = h;
        this.weight = w;
    }
    man.prototype.name = "man";
    man.prototype.double = function() {
        this.height *= 2;
        this.weigth *= 2;
    }
    function shawn() {
        man.apply(this, arguments);
    };
    
    function subclassOf(base) {
        _subclassOf.prototype= base.prototype;
        return new _subclassOf();
    }
    
    function _subclassOf() {};
    
    function SendMessage(msg) {
        document.getElementById("Console").innerHTML += msg + "<br />";
    }
    
    window.onload = function() {
        shawn.prototype = subclassOf(man);
        
        var p = new shawn(180, 90);
        SendMessage("Shawn height: " + p.height);
    }
    &lt;div id="Console"&gt;&lt;/div&gt;

    第三个例子说明你对shawn.prototype = man.prototype 的想法有什么问题,我会解释。 shawn 继承自 man,所以我添加了应该只影响 shawn 的新方法,称为 marriage(这当然会导致他增加一些体重;))-该方法应该 strong> 影响基类man,因为它不是从shawn 继承的,继承只是一种方式。但是....正如您在示例中看到的,普通的man 也可以结婚 - 大问题。

    function man(h, w) {
        SendMessage("man is created with height " + h + " and weight " + w);
        this.height = h;
        this.weight = w;
    }
    man.prototype.name = "man";
    man.prototype.double = function() {
        this.height *= 2;
        this.weight *= 2;
    }
    function shawn() {
        man.apply(this, arguments);
    };
    
    function SendMessage(msg) {
        document.getElementById("Console").innerHTML += msg + "<br />";
    }
    
    window.onload = function() {
        shawn.prototype = man.prototype;
        
        var p = new shawn(180, 90);
        SendMessage("Shawn height: " + p.height);
        p.double();
        SendMessage("Shawn height: " + p.height);
        
        shawn.prototype.marriage = function() {
           SendMessage("Shawn is getting married, current weight: " + this.weight);
           this.weight += 20;
        };
        
        p.marriage();
        SendMessage("Shawn weight: " + p.weight);
        
        var q = new man(170, 60);
        q.marriage();
        SendMessage("q weight: " + q.weight);
    }
    &lt;div id="Console"&gt;&lt;/div&gt;

    最后,第四个示例表明使用subclassOf 一切正常,因为shawn 正确继承man,而marriage 没有传递给基类。

    function man(h, w) {
        SendMessage("man is created with height " + h + " and weight " + w);
        this.height = h;
        this.weight = w;
    }
    man.prototype.name = "man";
    man.prototype.double = function() {
        this.height *= 2;
        this.weight *= 2;
    }
    function shawn() {
        man.apply(this, arguments);
    };
    
    function subclassOf(base) {
        _subclassOf.prototype= base.prototype;
        return new _subclassOf();
    }
    function _subclassOf() {};
    
    function SendMessage(msg) {
        document.getElementById("Console").innerHTML += msg + "<br />";
    }
    
    window.onload = function() {
        shawn.prototype = subclassOf(man);
        
        var p = new shawn(180, 90);
        SendMessage("Shawn height: " + p.height);
        p.double();
        SendMessage("Shawn height: " + p.height);
        
        shawn.prototype.marriage = function() {
           SendMessage("Shawn is getting married, current weight: " + this.weight);
           this.weight += 20;
        };
        
        p.marriage();
        SendMessage("Shawn weight: " + p.weight);
        
        var q = new man(170, 60);
        if (q.marriage)
            q.marriage();
        else
            SendMessage("marriage is undefined for man");
        SendMessage("q weight: " + q.weight);
    }
    &lt;div id="Console"&gt;&lt;/div&gt;

    希望这是有道理的! :)

    【讨论】:

    • 哇,非常感谢您的回答!这个解释很好解释,现在一切都说得通了。 p.s.我喜欢婚姻功能。 :)
    • @mikkol 当然,我的荣幸.. 希望我的婚姻假设不适用于你.. ;-)
    • 为了方便参考,我已经内联了你所有的代码示例 :)
    【解决方案2】:
    shawn.prototype = man.prototype;
    

    将共享原型,即修改一个将修改另一个。

    shawn.prototype = new man;
    

    会将shawn.prototype 设置为从man.prototype 继承的新创建的对象,因此对其的更改不会传播到man 实例。

    但是,使用new 意味着将执行构造函数man(),这可能会产生不希望的副作用。

    最好通过手动克隆原型

    shawn.prototype = Object.create(man.prototype);
    

    如果可用或custom clone function(与您的subclassOf 的工作方式相同)

    shawn.prototype = clone(man.prototype);
    

    否则。

    【讨论】:

      【解决方案3】:

      除了@Shadow 的出色回答之外,您还可以将shawn.prototype = man.prototype 认为是"shawn is the same as man",而不是"shawn is a man"

      【讨论】:

      • 是的,我没有意识到它们将被“链接”在一起以同时进行修改。谢谢!
      猜你喜欢
      • 2019-01-24
      • 2016-07-04
      • 1970-01-01
      • 2020-12-28
      • 2013-04-10
      • 1970-01-01
      • 1970-01-01
      • 2016-11-19
      相关资源
      最近更新 更多