ES5實現繼承的那些事

第一種方式是藉助call實現繼承:面試

function Parent1(){
    this.name = 'parent1';
  }
  function Child1(){
    Parent1.call(this);
    this.type = 'child1'
  }
  console.log(new Child1);
複製代碼

這樣寫的時候子類雖然可以拿到父類的屬性值,可是問題是父類原型對象中一旦存在方法那麼子類沒法繼承。那麼引出下面的方法。函數

第二種方式藉助原型鏈實現繼承:測試

function Parent2() {
    this.name = 'parent2';
    this.play = [1, 2, 3]
  }
  function Child2() {
    this.type = 'child2';
  }
  Child2.prototype = new Parent2();

  console.log(new Child2());
複製代碼

看似沒有問題,父類的方法和屬性都可以訪問,但實際上有一個潛在的不足。舉個例子:優化

var s1 = new Child2();
  var s2 = new Child2();
  s1.play.push(4);
  console.log(s1.play, s2.play);
複製代碼

能夠看到控制檯:ui

明明我只改變了s1的play屬性,爲何s2也跟着變了呢?很簡單,由於兩個實例使用的是同一個原型對象。this

那麼還有更好的方式麼?spa

第三種方式:將前兩種組合:我,prototype

function Parent3 () {
    this.name = 'parent3';
    this.play = [1, 2, 3];
  }
  function Child3() {
    Parent3.call(this);
    this.type = 'child3';
  }
  Child3.prototype = new Parent3();
  var s3 = new Child3();
  var s4 = new Child3();
  s3.play.push(4);
  console.log(s3.play, s4.play);
複製代碼

能夠看到控制檯:3d

以前的問題都得以解決。可是這裏又徒增了一個新問題,那就是Parent3的構造函數會多執行了一次(Child3.prototype = new Parent3();)。這是咱們不肯看到的。那麼如何解決這個問題?code

第四種方式: 組合繼承的優化1

function Parent4 () {
    this.name = 'parent4';
    this.play = [1, 2, 3];
  }
  function Child4() {
    Parent4.call(this);
    this.type = 'child4';
  }
  Child4.prototype = Parent4.prototype;
複製代碼

這裏讓將父類原型對象直接給到子類,父類構造函數只執行一次,並且父類屬性和方法均能訪問,可是咱們來測試一下:

var s3 = new Child4();
  var s4 = new Child4();
  console.log(s3)
複製代碼

子類實例的構造函數是Parent4,顯然這是不對的,應該是Child4。

第五種方式(最推薦使用):優化2

function Parent5 () {
    this.name = 'parent5';
    this.play = [1, 2, 3];
  }
  function Child5() {
    Parent5.call(this);
    this.type = 'child5';
  }
  Child5.prototype = Object.create(Parent5.prototype);
  Child5.prototype.constructor = Child5;
複製代碼

這是最推薦的一種方式,接近完美的繼承。

所以,小小的繼承雖然ES6當中簡化了不少,但毋庸置疑的是,js是一門基於原型的語言,因此,用ES5來完成繼承很是考驗面試者對JS語言自己的理解,尤爲是對於原型鏈是否理解清楚。

若是有更好的方式,歡迎在評論區交流。

相關文章
相關標籤/搜索