Javascript繼承

咱們用new一個構造函數的方法生成一個實例,好比:javascript

function a() { this.b=2; }

var b = new a()
複製代碼

new 這個關鍵字作了什麼?java

  • var b = {}
  • b.proto = a.prototype;
  • var res = a.call(b)
  • return typeof res === 'object' ? res : b;

當談到繼承時,JavaScript 只有一種結構:對象。每一個實例對象(object )都有一個私有屬性(稱之爲__proto__)指向它的原型對象(prototype)。給幾個例子,B繼承自A。es6

構造函數實現繼承

function parent(b) {
  console.log(b);    
  this.name = b;
}

console.log(parent); // 會打印出上述函數

parent.prototype.say = function () {
  console.log('abc');
};

function child (b) {
  parent.call(this, b);
  
  console.log(parent.call(this, b)); // call 會改造this
  
  this.xixi = 2;
}
複製代碼

有個缺陷,這個方法不能繼承父類的say方法函數

原型鏈繼承

原型鏈是 javascript 的典型繼承方式, 這種繼承方式的最大特色就是共享,全部事例共享原型對象中的全部屬性和方法。this

function parent(b) {
  this.name = b;
}

parent.prototype.xixi = '123';

function child() {
  this.a=1;
}

child.prototype = new parent(b);
child.prototype.constructor = parent // 保持構造函數和原型對象的完整性

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

缺點,new出來的實例經過參數傳值賦值的話,一經初始化就永久有個初始值了。因此是沒法向父類傳參,沒法實現多繼承的。spa

組合式繼承

簡單點來講就是構造函數繼承 + 原型鏈繼承,實現了繼承,這樣父類和子類能夠分別擁有本身的實例化屬性。prototype

function parent (b) {
  this.name = b;
}

function child (b) {
  parent.call(this, b);
  this.xixi = 1;
}

child.prototype = new parent();
child.prototype.constructor = child;
複製代碼

既是子類的實例,也是父類的實例, 但有一個缺點就是調用了兩次父類構造函數,形成內存浪費。並且可能發生變量覆蓋問題。code

寄生組合式繼承

改進了一步,使用了Object.create方法,不會形成內存浪費。對象

function parent (b) {
  this.name = b;
}

function child (b) {
  parent.call(this, b);
  this.xixi = 1;
}

child.prototype = Object.create(parent);
child.prototype.constructor = child;
複製代碼

es6 extends

也有寄生組合式繼承的優勢,經過super來傳遞父類拿到的參數繼承

class parent {
  constructor(prop) {
    console.log(prop);
  }
}
class child extends parent {
  constructor(prop) {
    super(prop);
    console.log(prop)
  }
}
new child('bb')
複製代碼
相關文章
相關標籤/搜索