[英]How to inherit right from parent prototype JS
問題 - 如何將正確的方法從父(Animal)繼承到子(Rabbit)原型,這些原型在創建對象后不會覆蓋父原型道具,基於子原型。 我的意思是,創建對象(兔子)必須從Rabbit原型獲取原型方法(.prototype.walk),而不是從父級(Animal)。
我知道我們可以輕松解決並移動方法this.walk構造函數Animal后面並創建原型方法Animal.prototype.walk ...但是我想知道我們是否可以在不推動this.walk從構造函數括號中執行此操作? 是一些JS trik?
我會感激任何答案,謝謝!
function Animal(name) {
this.name = name;
this.walk = function() {
console.log( "walk " + this.name );
};
}
// Animal.prototype.walk = function() { //// we can not use this trik and
// console.log( "walk " + this.name ); //// delete this.walk function in
//} //// constructor
function Rabbit(name) {
Animal.apply(this, arguments);
}
Rabbit.prototype = Object.create(Animal.prototype);
Rabbit.prototype.constructor = Rabbit;
Rabbit.prototype.walk = function() {
console.log( "jump " + this.name );
};
var rabbit = new Rabbit("Rabbit");
rabbit.walk(); // for now we get "walk Rabbit". But need - "jump Rabbit"
如果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
,但這可能會讓任何認為該方法被繼承的讀者感到困惑)
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)
直接在rabbit
實例上添加了一個walk
函數。
解決這個問題的方法是定義你的兩個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"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.