使用prototype /"new"继承

mik*_*kol 5 javascript oop

嗨,我是Javascript OO的新手,想要了解有关继承的更多信息.希望你能提供一些建议!

我看到这篇精彩文章: 如何在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;
Run Code Online (Sandbox Code Playgroud)

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

function subclassOf(base) {
    _subclassOf.prototype= base.prototype;
    return new _subclassOf();
}
function _subclassOf() {};
shawn.prototype = subclassOf(man);
Run Code Online (Sandbox Code Playgroud)

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

shawn.prototype = man.prototype;
Run Code Online (Sandbox Code Playgroud)

我觉得它的作用完全一样.还是有什么我想念的?提前致谢!

Sha*_*ard 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);
}
Run Code Online (Sandbox Code Playgroud)
<div id="Console"></div>
Run Code Online (Sandbox Code Playgroud)

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

第二个例子证明了使用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);
}
Run Code Online (Sandbox Code Playgroud)
<div id="Console"></div>
Run Code Online (Sandbox Code Playgroud)

第三个例子说明你的想法有什么问题,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);
}
Run Code Online (Sandbox Code Playgroud)
<div id="Console"></div>
Run Code Online (Sandbox Code Playgroud)

最后,第四个例子表明使用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);
}
Run Code Online (Sandbox Code Playgroud)
<div id="Console"></div>
Run Code Online (Sandbox Code Playgroud)

希望这有一定道理!:)


Chr*_*oph 5

shawn.prototype = man.prototype;
Run Code Online (Sandbox Code Playgroud)

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

shawn.prototype = new man;
Run Code Online (Sandbox Code Playgroud)

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

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

最好通过手动克隆原型

shawn.prototype = Object.create(man.prototype);
Run Code Online (Sandbox Code Playgroud)

如果可用或自定义克隆功能(其工作方式与您的相同subclassOf)

shawn.prototype = clone(man.prototype);
Run Code Online (Sandbox Code Playgroud)

除此以外.