0

当涉及到 JavaScript 原型继承时,我以为我完全理解了自己在做什么。原来这是一个残忍的情妇。这是我想出的一个例子,我使用 Pokemon(是的,Pokemon ...)来展示不同的进化如何相互继承。

function Squirtle(firstPower) {
    this.firstPower = firstPower;
}
Squirtle.prototype.useFirstPower = function () {
    console.log("Using " + this.firstPower);
}
function Wartortle(firstPower, secondPower) {
    Squirtle.call(this, firstPower);
    this.secondPower = secondPower;
}
Wartortle.prototype.useSecondPower = function () {
    console.log("Using " + this.secondPower);
}
var mySquirtle = new Squirtle("water squirt");
mySquirtle.useFirstPower(); //works

//squirtle evolved
mySquirtle.prototype = Object.create(Wartortle.prototype);
mySquirtle.useSecondPower(); //no method found

这里想要的效果是保留 的prototype方法Wartortle.prototype和 的方法Sqruitle.prototype。我假设通过Squirtle.call(...)Wartortle构造函数中使用将允许我继承所有方法。显然不是。我觉得我比以往任何时候都迷失了这些东西。

如何正确继承并保留超级和子构造函数的所有方法?我在这里做错了什么?

编辑

如下所述,我可以使用创建一个新对象,new Wartortle但我认为我所追求的是将原始对象全部扩充在一起。这将如何工作或不工作?

4

2 回答 2

2

这就是“正常”继承的工作方式:

function Squirtle(firstPower) {
    this.firstPower = firstPower;
}
Squirtle.prototype.useFirstPower = function () {
    console.log("Using " + this.firstPower);
}
function Wartortle(firstPower, secondPower) {
    Squirtle.call(this, firstPower);
    this.secondPower = secondPower;
}

//Wartortle inherits from Squirtle
Wartortle.prototype = Object.create(Squirtle.prototype);
//Wartortle methods
Wartortle.prototype.useSecondPower = function () {
    console.log("Using " + this.secondPower);
}
var mySquirtle = new Squirtle("water squirt");
var myWartortle = new Wartortle("water squirt plus", "ice blast");

现在您可以分别创建 squirtle 和 wartortle 对象,每个 warttortle 实例都继承 squirtle 的方法。

现在,如果您有一个 squirtle 对象并想将其转换为 warttle 对象,您基本上有两个选择:

1)写一个变换函数:

function transform(squirtle, secondPower) {
    return new Wartortle(squirtle.firstPower, secondPower);
}

2)或者您操纵__proto__属性,据我所知,这是真正将对象更改为另一个构造函数的实例的唯一方法:

squirtle.__proto__ = Wartortle.prototype;
squirtle.secondPower = "awsome secone power";

不过,我会坚持第一种方法,因为__proto__并非所有地方都支持。

于 2013-08-03T16:59:43.030 回答
1

如果你想让你的 squirtle 变成 wartortle,你不应该创建一个新对象吗?

mySquirtle = new Wartortle("water squirt", "water gun");
mySquirtle.useSecondPower();
=> Using water squirt
=> Using water gun

编辑

要转换 squirtle,您可以为对象本身分配一个新原型并设置二次幂:

mySquirtle.__proto__ = Wartortle.prototype;
mySquirtle.secondPower = "water gun";

编辑 2

更改对象的问题是原型是针对函数的,而不是针对使用new. 因此,如果您要更改原型,Squirtle您将赋予所有松鼠新的权力。

对象有对其原型的引用,但本身没有原型:

console.log(mySquirtle.prototype);
=> undefined

所以你可以直接将方法添加到对象中,但是你会在对象上定义很多重复的函数,而不是在一个原型上定义。

于 2013-08-03T16:53:16.710 回答