溫習js中對象的繼承

溫故而知新 XDes6

1. 關於原型和構造函數的幾個知識要點:

  1. 使用new 操做符調用構造函數,會經歷如下四個步驟:
    1.1. 建立一個新對象;
    1.2. 將構造函數的做用域賦給新對象(所以 this 就指向了這個新對象);
    1.3. 執行構造函數中的代碼(爲這個新對象添加屬性);
    1.4. 返回新對象。
  2. 當調用構造函數建立一個新實例後,該實例的內部將包含一個指針(內部屬性:__proto__),指向構造函數的原型對象(因此能夠在構造函數的 prototype 裏存放實例公用的方法)。
  3. 每當代碼讀取某個對象的某個屬性時,都會進行一次搜索,目標是具備給定名字的屬性。搜索從對象實例自己開始。若是在實例中找到了該屬性,則 return 該屬性的值;若是沒有找到,則搜索內部指針指向的原型對象( __proto__ ),若找到,則 return 該屬性值;若沒找到,繼續搜索原型的原型...

2. 實現

給出父類 Animal,實現子類Cat:函數

function Animal (name) {
    this.name = name
    this.brother = 'Tony'
}

Animal.prototype.eat = function (thing) {
    console.log(this.name + ' eat ' + thing);
}

2.1 組合繼承(結合原型鏈和借用構造函數,不太完美)

function Cat (name) {
    Animal.call(this,name)   // 借用構造函數,繼承父類屬性
    this.sister = 'May'
}

Cat.prototype = new Animal()   // 原型鏈,繼承父類方法
/* 在prototype繼承了父類實例的所有屬性,存在冗餘。屬性的繼承已經在構造函數內經過調用父類構造函數實現。
實際上,子類的prototype須要的只是父類實例中指向父類原型的內部指針: Cat.prototype.__proto__ =  Animal.protype   */

console.log(Cat.prototype)
//  {name: undefined(冗餘), brother: "Tony"(冗餘), constructor: ƒ}

Cat.prototype.constructor = Cat    // 因爲上面 Cat.prototype 進行了賦值,因此須要從新指定其構造函數。
// 這一步對 instanceof 無影響,由於  "instanceof 運算符用來測試一個對象在其原型鏈中是否存在一個構造函數的 prototype 屬性" ;影響的是Cat實例的constructor 屬性。
// 若是不作這一步:var Tom = new Cat('Tom'); Tom.constructor  ==>  Animal

2.2 寄生組合繼承(完美)

function Cat (name) {
    Animal.call(this,name)
    this.sister = 'May'
}

function createObject (obj) {  /* 建立一個新對象,使用現有的對象來提供新建立的對象的__proto__ ,至關於 Object.create()  */
    function F () {}
    F.prototype = obj
    return new F()    
}

Cat.prototype = createObject (Animal.prototype)
// 至關於 Cat.prototype = Object.create(Animal.prototype)

console.log(Cat.prototype)
//  {constructor: ƒ}

Cat.prototype.constructor = Cat

2.3 ES6語法

class Animal {
  constructor(name){
    this.name = name
    this.brother = 'Tony'
  }

  eat(thing) {
    console.log(this.name + ' eat ' + thing);
  }
}

class Cat extends Animal {
  constructor(name) {
    super(name)  
    /* super()表示調用父類構造函數,this指向子類。只有調用super以後,纔可使用this關鍵字,不然新建實例時會報錯。*/
    /* 另:super做爲對象時,在普通方法中,指向父類的原型對象;在靜態方法中,指向父類。經過super調用父類方法時,方法內部this指向子類;對super的猴哥屬性賦值時,super就是this,賦值的屬性會變成子類實例的屬性 (不清楚裏面是什麼魔法)*/

    this.sister = 'May'
  }
}
相關文章
相關標籤/搜索