问题 - 如何将正确的方法从父(Animal)继承到子(Rabbit)原型,这些原型在创建对象后不会覆盖父原型道具,基于子原型。我的意思是,创建对象(兔子)必须从Rabbit原型获取原型方法(.prototype.walk),而不是从父级(Animal)。
我知道我们可以轻松解决并移动方法this.walk在构造函数Animal后面并创建原型方法Animal.prototype.walk ...但我想知道我们是否可以在不推送this.walk构造函数的情况下执行此操作括号?这是一些JS trik?
我会感激任何答案,谢谢!
BangPatterns
答案 0 :(得分:2)
如果Animal
构造函数在每个实例上定义.walk
函数,要覆盖它们,Rabbit
构造函数必须执行相同的操作:
function Rabbit(name) {
Animal.apply(this, arguments); // creates an own .walk property
// overwrites the own .walk property
this.walk = function() {
console.log( "jump " + this.name );
};
}
您还可以共享函数对象以获得更好的内存使用:
function rabbitWalkMethod() {
console.log( "jump " + this.name );
}
function Rabbit(name) {
Animal.apply(this, arguments);
this.walk = rabbitWalkMethod;
}
(您也可以使用Rabbit.prototype.walk
属性来存储它而不是本地变量rabbitWalkMethod
,但这可能会让任何认为该方法被继承的读者感到困惑)
答案 1 :(得分:1)
TL; DR:您正在混合使用两种不同的方法来定义JavaScript中的方法。你应该选择一种方法来坚持下去。
使用Animal
,您将在构造函数体内定义walk
方法。这将在每次调用构造函数时创建一个新函数。它易于阅读,但会浪费内存,因为每个实例都有自己相同的walk
方法。
使用Rabbit
,您正在利用Rabbit prototype
,因此每个实例共享一个walk
函数。您可以将JS中的原型视为备份对象。 JS首先在实例本身上查找属性。如果没有找到,它将在“原型链”上运行,直到它找到属性或用完原型。
例如,使用您的代码,如果我调用rabbit.toString()
,我最终会向上移动链接:
rabbit.toString --> undefined
Rabbit.prototype.toString --> undefined
Animal.prototype.toString --> undefined
Object.prototype.toString --> ƒ toString() { [native code] }
但是,当您致电rabbit.walk()
时,它永远不会使它成为第一个原型,因为Animal.apply(this, arguments)
将walk
函数直接添加到rabbit
实例上。
解决此问题的方法是在构造函数体中定义两个walk
方法两者(最好)或两者。
或者,你可以利用ES6语法,它将你的walk
方法放在后台的原型上,但看起来比手动更清晰:
class Animal {
constructor (name) {
this.name = name
}
walk () {
console.log(`walk ${this.name}`)
}
}
class Rabbit extends Animal {
walk () {
console.log(`jump ${this.name}`)
}
}
const rabbit = new Rabbit('Rabbit')
rabbit.walk() // "jump Rabbit"