js之繼承實現方法

js的繼承方式有很多,本文主要介紹以下幾種:構造函數繼承、原型鏈繼承、組合繼承、es6中的class繼承這四種。

一、構造函數繼承

構造函數一般命名時首字母大寫,用來區分於普通函數,內部使用的this對象來指向即將要生成的實例對象,使用New來生成實例對象。

// 這是一個構造函數
function Animal(name) {
  this.name = name;
  this.showName = function() {
    console.log(this.name);
  };
}

function Cat(name) {
  Animal.call(this, name);
  //Animal.bind(this)(name)
  //Animal.apply(this, [name])
}

let cat = new Cat("我是一隻貓");
cat.showName();

補充知識:
 call、apply、bind方法的作用都是改變函數的執行環境,第一個參數傳入上下文執行環境(this),然後傳入函數執行所需的參數。

優點:

  1. 可以在子類型構造函數中向Parent傳遞參數
  2. 避免了引用類型的屬性被所有實例共享

缺點: 

  1. 只能繼承構造函數中的屬性和方法,而無法繼承原型鏈上的屬性和方法

二、原型鏈繼承

利用原型鏈來實現繼承就是讓父類的一個實例作爲子類的原型 

// 這是一個構造函數
function Animal(name) {
  this.name = name;
  this.showName = function() {
    console.log(this.name);
  };
}

function Cat() {}

//父類的一個實例作爲子類的原型
Cat.prototype = new Animal("我是一隻貓");
// 注意這裏new Animal()生成的父類對象並沒有constructor屬性,故需添加上
Cat.prototype.constructor = Cat;

let cat = new Cat();
cat.showName();

優點:

  1.  能夠繼承父類構造函數及其原型鏈上的全部屬性和方法

缺點: 

  1. 引用類型的屬性被所有實例共享,一改全改
  2. 在創建 Child 的實例時,不能向Parent傳參

三、組合繼承

組合構造函數及原型鏈兩種繼承方法,從而解決他們存在的缺點

// 這是一個構造函數
function Animal(name) {
  this.name = name;
  this.showName = function() {
    console.log(this.name);
  };
}

function Cat(name) {
  Animal.apply(this, [name]); //第二次調用
}

//父類的一個實例作爲子類的原型
Cat.prototype = new Animal();
// 注意這裏new Animal()生成的父類對象並沒有constructor屬性,故需添加上
Cat.prototype.constructor = Cat;

let cat = new Cat("我是一隻貓");
cat.showName();

優點:

  1. 解決了原型鏈繼承和構造函數繼承存在的問題

缺點: 

  1. 父類的構造函數被調用兩次

四、class繼承

利用ES6中的extends,寫法更加面向對象,原理還是原型鏈

class Animal {
  constructor(name) {
    this.name = name;
  }
  showName() {
    console.log(this.name);
  }
}

class Cat extends Animal {
  constructor(name) {
    super(name);  //不能少,而且必須寫在this前邊
    this.type = "寵物";
  }
  showType() {
    console.log(this.type);
  }
}

let cat = new Cat("我是一隻貓");
cat.showName();
cat.showType();

優點:

  1. 實現更簡單,且不存在不能傳參等問題

補充知識super :

super關鍵字可以當作函數 super() 使用,也可以當作對象 super 使用

1.當做函數使用

在constructor中,表示父類的構造函數,並且子類的構造函數必須執行一次super,即super(name)相當parent.prototype.constructor.call(this,name)

  constructor(name) {
    super(name);
    this.type = "寵物";
  }

super()也可寫在子類的構造函數中,寫在自定義函數中會報錯。 

2.當做對象使用

靜態方法中指向父類,在普通方法中指向父類的原型

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章