簡體   English   中英

如何從父原型JS繼承權利

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM