看了这个video后,我学到了一种用Javascript实现继承的好方法:原型继承。此方法使用Object.create / Object.assign基于另一个实例创建新对象。这似乎非常有趣,因为它很容易理解发生了什么。例如:
const human = {
species: 'human',
create: function(values) {
const instance = Object.create(this);
Object.assign(instance, values);
return instance;
},
sayName: function() {
console.log(`Hi, my name is ${this.name}`);
},
saySpecies: function() {
console.log(`Hi, I'm a ${this.species}`);
}
}
const musician = human.create({
species: 'musician',
playInstrument: function() {
console.log(`I'm a musician and I play ${this.instrument}`);
}
});
const aHuman = human.create({ name: 'Paul' });
aHuman.sayName();
aHuman.saySpecies();
const aMusician = musician.create({ name: 'David', instrument: 'Guitar' });
aMusician.sayName();
aMusician.saySpecies();
aMusician.playInstrument();
// how to check if musician is an instance of human?
console.log(musician instanceof human);

使用经典继承,我可以使用instanceof
来了解给定对象的链中是否有给定的 proto (例如musician instanceof Human
)。
这就是 proto 链的样子,看起来与使用new
运算符创建的非常相似。
问题 如何通过原型继承实现同样的目标?
答案 0 :(得分:1)
您的代码不使用继承。创建新对象的唯一位置是这一行:
return Object.assign({}, this, values);
// ^^ here
{}
创建一个继承自Object.prototype
的新对象。这就像做Object.create(Object.prototype)
或new Object()
。
您的代码中的任何内容都不会继承自human
或musician
。
答案 1 :(得分:1)
您的尝试有两个主要问题:
instanceof
的RHS必须是一个函数,因此您的类型必须建立在函数之上。create
是一种类型方法。 sayName
是一种实例方法。以下内容应该按照您的预期运作。
function Human(){}
Object.assign(Human, {
create: function(values) {
let newObj = Object.create(this.prototype);
return Object.assign(newObj, values);
}
});
Object.assign(Human.prototype, {
species: 'human',
sayName: function() {
console.log(`Hi, my name is ${this.name}`);
},
saySpecies: function() {
console.log(`Hi, I'm a ${this.species}`);
}
});
function Musician(){}
Object.assign(Musician, Human);
Musician.prototype = Human.create({
species: 'musician',
playInstrument: function() {
console.log(`I'm a musician and I play ${this.instrument}`);
}
});
const aHuman = Human.create({ name: 'Paul' });
aHuman.sayName();
aHuman.saySpecies();
const aMusician = Musician.create({ name: 'David', instrument: 'Guitar' });
aMusician.sayName();
aMusician.saySpecies();
aMusician.playInstrument();
// how to check if musician is an instance of human?
console.log(aMusician instanceof Human);
答案 2 :(得分:0)
@ JLRishe的答案有效。但是如果你想避免使用函数并继续使用对象,你可以实现自己的instanceof版本。此代码段也有效:
const human = {
species: 'human',
create: function(values) {
let newObj = Object.create(this);
return Object.assign(newObj, values);
},
instanceof: function(obj) {
if (!Object.getPrototypeOf(this)) {
return false;
}
let isPrototypeOf = (
this === obj ||
Object.getPrototypeOf(this) === obj ||
this === Object.getPrototypeOf(obj) ||
Object.getPrototypeOf(this) === obj.prototype
);
if (!isPrototypeOf) {
isPrototypeOf = this.instanceof.call(Object.getPrototypeOf(this), obj);
}
return isPrototypeOf;
},
sayName: function() {
console.log(`Hi, my name is ${this.name}`);
},
saySpecies: function() {
console.log(`Hi, I'm a ${this.species}`);
}
}
const musician = human.create({
species: 'musician',
playInstrument: function() {
console.log(`I'm a musician and I play ${this.instrument}`);
}
});
const aHuman = human.create({ name: 'Paul' });
aHuman.sayName();
aHuman.saySpecies();
const aMusician = musician.create({ name: 'David', instrument: 'Guitar' });
aMusician.sayName();
aMusician.saySpecies();
aMusician.playInstrument();
var test = {};
console.log(human.instanceof(human));
console.log(musician.instanceof(human));
console.log(musician.instanceof(Object));
console.log(aHuman.instanceof(human));
console.log(aMusician.instanceof(human));
console.log(aHuman.instanceof(musician));
console.log(aHuman.instanceof(Object));
console.log(aMusician.instanceof(musician));
console.log(musician.instanceof(test));
console.log(human.instanceof(test));
console.log(aMusician.instanceof(test));
console.log(aHuman.instanceof(test));