原型继承和Object.create
Prototypal inheritance and Object.create
当谈到JavaScript原型继承时,我想我完全明白自己在做什么。原来是个残忍的情妇。下面是我用口袋妖怪(是的,口袋妖怪…)来展示不同进化如何相互继承的例子。
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
这里期望的效果是保持Wartortle.prototype
的prototype
方法和Sqruitle.prototype
的方法。我假设在Wartortle
构造函数中使用Squirtle.call(...)
将允许我继承所有方法。显然不是。我觉得我对这些东西比以往任何时候都更失落。
如何正确继承并保留超级构造函数和子构造函数的所有方法??我在这里做错了什么?
编辑
如下所述,我可以使用new Wartortle
创建一个新对象,但我认为我所追求的是将原始对象全部扩充在一起。这是怎么回事?
这就是"正常"惯性的工作方式:
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");
现在,您可以分别创建喷射和wartortle对象,每个wartortle实例都继承了喷射的方法。
现在,如果你有一个喷射物体,并想把它转换成一个战斧物体,你基本上有两个选择:
1) 编写一个转换函数:
function transform(squirtle, secondPower) {
return new Wartortle(squirtle.firstPower, secondPower);
}
2) 或者操作__proto__
属性,据我所知,这是真正将对象更改为另一个构造函数实例的唯一方法:
squirtle.__proto__ = Wartortle.prototype;
squirtle.secondPower = "awsome secone power";
不过,我会坚持第一种方法,因为__proto__
并不是所有地方都支持的。
如果你想让你的喷射器成为战斧,你不应该创建一个新对象吗?
mySquirtle = new Wartortle("water squirt", "water gun");
mySquirtle.useSecondPower();
=> Using water squirt
=> Using water gun
编辑
要转换喷射器,您可以将其分配给对象本身一个新的原型,并设置第二次幂:
mySquirtle.__proto__ = Wartortle.prototype;
mySquirtle.secondPower = "water gun";
Edt 2
更改对象的问题是原型是为函数而设,而不是为使用new
创建的对象而设。因此,如果你要改变Squirtle
的原型,你将赋予所有喷射器新的力量。
对象有对其原型的引用,但本身没有原型:
console.log(mySquirtle.prototype);
=> undefined
因此,您可以直接将方法添加到对象中,但随后将在对象上定义许多重复的函数,而不是在一个原型上定义。
- 使用Object.create()的角度服务继承
- 在使用object.create创建的对象中使用super
- 正在使用object.create()创建XMLHttpRequest对象
- Object.create()只读名称属性
- childObj.prototype = Object.create(parentObj.prototype) 和 ch
- object.create 不使用我的新值
- Object.create() instead of prototype
- Object.create and Prototypes
- Javascript Object.create
- 使用Object.create作为原型的原型继承将[Object]作为实例的原型
- 不涉及私有“函数”的“Object.create”的自定义实现
- 正在对通过object.create创建的对象设置原型
- javascript中的Object.create方法
- 重写JavaScript中的Object.create方法
- 在不使用object.Create的情况下创建具有null原型的javascript对象
- JavaScript inheritance Object.create
- 为什么MDN Object.create polyfill上的Temp.prototype设置为null
- 使用Object.create()创建对象的模式
- 使用“new”关键字创建的对象和使用“Object.create”创建的对象给出不同的结果
- Object.create(Object.prototype)、Object.create(Object)和Object