本篇部落格主要來整合一下js繼承的六種方式及其優缺點。首先我們提供乙個父類:
// 父類
function person(name)
}
本節中我們使用到的子類如下:
// 子類
function staff(office)
}
staff.prototype = new person('staff');
const a = new staff('d302');
const b = new staff('d232');
a.showname(); // satff
a.showoffice(); // d302
b.showname(); // staff
b.showoffice(); // d232
上述語句即為原型鏈繼承,此時,a
與b
有乙個共有屬性name
,要注意此時name為基本資料型別,而原型鏈繼承構造的子物件之間共享的是引用資料型別,如果我單獨對a
的name
屬性進行修改,那麼b
的name
屬性不會因此而改變。舉例說明如下:
staff.prototype = new person('staff');
const a = new staff('d302');
const b = new staff('d232');
a.name = 'change'
a.showname(); // change
b.showname(); // staff
但是,如果person
物件的name
屬性值引用型別的話,那麼構造出的子物件的屬性就有可能會受到影響,例項如下:
staff.prototype = new person([1,2,3]);
const a = new staff('d302');
const b = new staff('d232');
a.showname(); // [1,2,3]
b.showname(); // [1,2,3]
a.name.push(4);
a.showname(); // [1,2,3,4]
b.showname(); // [1,2,3,4]
a.name = [1,2]
a.showname(); // [1,2]
b.showname(); // [1,2,3,4]
大家可以看到如上兩種情況,我在往name
屬性裡面push的時候a
和b
的屬性值都發生了變化,但是我在將a
的name
屬性重新賦值為[1,2]時,b
的name
值並沒有發生變化。這是因為進行push
操作之後引用資料型別的位址值並沒有發生變化,而b
的name
屬性指向的位址與a
的name
屬性指向的位址相同,所以a
和b
會同時發生變化。但是我將其重新複製時,a
的name
屬性指向的位址發生了變化,b指向的還是原來的位址,所以a
和b
並沒有發生同步變化。
優點: 能通過instanceof
和isprototypeof
的檢測
缺點:
父物件中的屬性也變成了子物件的prototype中的公用屬性
2. 不能向父型別的建構函式中傳遞引數
3. 只能繼承乙個父類
function staff(name, office)
}const a = new staff('a', 'd302');
const b = new staff('b', 'd232');
a.showname(); // a
b.showname(); // b
console.log(a instanceof person); // false
通過這個例項我們可以看出我們可以向父類傳遞引數了,並且可以繼承多個父類函式,只要呼叫多次call
函式即可.
優點:
可以向父類傳遞引數
可以實現多父類繼承
父類的屬性不會被子類共享
缺點:呼叫建構函式的話就相當於在每個新建物件內都有乙個獨立的屬性已經函式,staff
與person
並不能使用instanceof
方法,兩者並不存在指向關係,函式復用並沒有派上用場。
function staff(name, office)
}staff.prototype = new person();
const a = new staff('a', 'd302');
const b = new staff('b', 'd232');
a.showname(); // a
b.showname(); // b
console.log(a instanceof person); // true
這種方法就是對原型鏈繼承和建構函式繼承的結合。
優點:
繼承前兩者的優點
可以實現對建構函式的復用
缺點:呼叫了兩次父類建構函式,更耗記憶體
function container(obj)
f.prototype = obj;
return new f();
}const child = new person('child');
const staff = container(child);
staff.showname(); // child
這種繼承方式其實可以看做是直接複製了父類。
缺點:無法復用
function container(obj)
f.prototype = obj;
return new f();
}function staff(obj, office)
return sub;
}const child = new person('child');
const a = staff(child, 'd232');
const b = staff(child, 'c433');
a.showname(); // child
a.showoffice(); // d232
b.showname(); // child
b.showoffice(); // c433
這種繼承方式就是在原型式繼承的基礎上又加了乙個函式用來新增加屬性,解決了原型式繼承需要後續增加屬性的問題。
寄生組合式繼承強化的部分就是在組合繼承的基礎上減少一次多餘的呼叫父類的建構函式:
function staff(name, office)
}staff.prototype = object.create(person.prototype);
staff.prototype.constructor = person;
const a = new staff('a', 'd232');
const b = new staff('b', 'c433');
a.showname(); // a
a.showoffice(); // d232
b.showname(); // b
b.showoffice(); // c433
js繼承的6種方式
想要繼承,就必須要提供個父類,繼承誰,提供繼承的屬性 function person name person.prototype.age 10 給建構函式新增了原型屬性function per per.prototype newperson var per1 newper console.log p...
繼承及ES6繼承
物件導向的三大特點 多型 繼承 封裝 繼承 乙個型別的物件能夠訪問另外乙個型別的屬性和方法 函式 類與類之間的關係 類就是眾多例項共有的屬性和方法的乙個抽象 原型物件中的this指向例項 function person var person newperson person只是乙個例項 consol...
繼承 ES6的繼承語法
什麼是繼承?繼承是發生在父子級關係中的現象 繼承 是 建構函式 的高階應用 就是兩個互為父子級關係的建構函式的應用 子級建構函式,繼承的是父級建構函式的屬性和方法 常見的繼承操作,分為 es5 的繼承語法 和 es6 的繼承語法 實際專案中一般不會直接使用繼承語法,一般都是通過框架來完成繼承,不用專...