建構函式式繼承
function Parent(n,walk){
this.name = n;
}
Parent.prototype.a = 'a';
function Child(name){
//子類繼承父類name屬性
Parent.call(this,name);
}
let baby = new Child('baby'); // baby
baby.a; //undefined
建構函式缺點:子類無法繼承父類原型物件上的屬性,兩個類的原型物件是相互獨立的。子類只能繼承建構函式掛載在例項上的屬性;
原型鏈繼承
實現原理:將子類原型物件變為父類的例項,則可以繼承它的原型物件,解決了建構函式的缺點
function Parent(){}
Parent.prototype.a = 'a';
Parent.prototype.array = [1,2,3];
function Child(){}
Child.prototype = new Parent()
(new Child()).__proto__ === new Parent(); //true
// 子類例項的原型物件等於父類的例項,也就是說子類實際上等於父類的例項
(new Child()).__proto__.__protp__ === Parent.prototype //true
//用過原型鏈繼承,子類例項的原型(父類例項)的原型的物件等於父類的原型物件
Child.prototype.__proto__ === Parent.prototype //true
//baby.__proto__.__proto__ = Parent.prototype 由此可知子類例項baby的原型的原型等於 父類的原型
let baby = new Child();
baby.__proto__ === Child.prototype //true
baby.__proto__.__proto__ = Parent.prototype //true
let anotherbaby = new Child();
baby.a;//a
baby.array;// [1,2,3]
anotherbaby.array.push(4);
//因為baby和anotherbaby的原型都指向父類原型,所以當屬性值為引用型別時一個修改了會影響另外一個
baby.array // [1,2,3,4]
構造原型式繼承
組合繼承方式可以解決例項繼承原型物件屬性互相影響的問題
function Parent(name){
this.name=name
//引用型別不要放到原型物件上
this.arr = arr;
}
function Child(name){
//繼承父類的建構函式
Parent.call(this,name,arr)
}
//用Object.create()介面重新建立一個和Parent.prototype一樣的物件
let prototype = Object.create(Parent.peototype)
//但是這時prototype.constructor = Parent的建構函式 需要改為Child
prototype.constructor = Child
//繼承父類的原型物件
Child.prototye = prototype