使用prototype /“new”继承

时间:2011-01-06 07:03:15

标签: javascript oop

您好我是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;

我认为它的工作方式完全相同。还是有什么我想念的?提前谢谢!

3 个答案:

答案 0 :(得分:10)

嗯,在我的拙见中,例子比言辞更好。以下所有示例都使用了您的代码,并添加了一些内容。

第一个例子将证明使用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);
}
<div id="Console"></div>

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

第二个例子证明使用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);
}
<div id="Console"></div>

第三个例子显示了你对shawn.prototype = man.prototype的想法有什么问题,我会解释一下。 shawn继承自man,因此我添加了仅应影响shawn的新方法,称为marriage(这当然会让他获得一些权重;)) - 方法会影响基类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);
}
<div id="Console"></div>

最后,第四个示例显示使用subclassOf一切正常,因为shawn正确地继承man,而marriage未传递给基类。< / p>

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);
}
<div id="Console"></div>

希望这有一定道理! :)

答案 1 :(得分:5)

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

否则。

答案 2 :(得分:1)

除了@ Shadow的优秀答案,您可以将shawn.prototype = man.prototype视为"shawn is the same as man",而不是"shawn is a man"