JS?的繼承方式與使用場景對比分析
在 JavaScript 中,繼承的實現(xiàn)方式主要有以下幾種,每種方式適用于不同的場景:
一、原型鏈繼承
實現(xiàn)方式:
function Parent() { this.name = 'Parent'; } Parent.prototype.say = function() { return this.name; }; function Child() {} Child.prototype = new Parent(); // 原型繼承關(guān)鍵 const child = new Child(); child.say(); // 輸出 "Parent"
特點:
- 子類實例通過原型鏈訪問父類屬性和方法
- 問題:父類的引用類型屬性會被所有子類實例共享
場景:
- 簡單繼承結(jié)構(gòu),無引用類型共享問題需求的場景
- 老項目快速實現(xiàn)繼承(現(xiàn)代開發(fā)不推薦優(yōu)先使用)
二、構(gòu)造函數(shù)繼承
實現(xiàn)方式:
function Parent(name) { this.name = name; } function Child(name) { Parent.call(this, name); // 構(gòu)造函數(shù)繼承關(guān)鍵 } const child = new Child('Child'); child.name; // 輸出 "Child"
特點:
- 將父類屬性復(fù)制到子類實例
- 優(yōu)點:解決引用屬性共享問題
- 缺陷:無法繼承父類原型上的方法
場景:
- 需要 實例屬性獨立性的場景(如每個對象需要獨立狀態(tài))
- 不支持子類復(fù)用父類原型方法(若無需復(fù)用則合適)
三、組合繼承(經(jīng)典繼承)
實現(xiàn)方式:
function Parent(name) { this.name = name; } Parent.prototype.say = function() { return this.name }; function Child(name) { Parent.call(this, name); // 第1次調(diào)用父類構(gòu)造函數(shù) } Child.prototype = new Parent(); // 第2次調(diào)用父類構(gòu)造函數(shù)(問題根源) Child.prototype.constructor = Child; const child = new Child('Child'); child.say(); // 輸出 "Child"
特點:
- 結(jié)合原型鏈繼承(方法繼承)和構(gòu)造函數(shù)繼承(屬性繼承)
- 缺陷:父類構(gòu)造函數(shù)被調(diào)用兩次,子類原型中存在冗余屬性
場景:
- 傳統(tǒng)項目的常規(guī)繼承需求(ES6 出現(xiàn)前的常見方案)
- 需要同時滿足方法復(fù)用和實例屬性獨立的場景
四、原型式繼承
實現(xiàn)方式:
const parent = { name: 'Parent', friends: ['Alice'] }; const child = Object.create(parent); // 核心API child.name = 'Child'; child.friends.push('Bob'); // friends被所有基于parent創(chuàng)建的對象共享
特點:
- 類似于對象淺拷貝
- 問題:引用類型屬性共享(與原型鏈相同)
場景:
- 簡單對象繼承需求(無構(gòu)造函數(shù)存在的場景)
- 原型鏈的極簡替代方案(如舊環(huán)境無
Object.create
時的polyfill
)
五、寄生式繼承
實現(xiàn)方式:
function createChild(parent) { const obj = Object.create(parent); obj.sayHi = () => 'Hi'; // 添加額外方法 return obj; } const child = createChild({ name: 'Parent' });
特點:
- 工廠模式增強對象
- 缺陷:方法無法復(fù)用,類似構(gòu)造函數(shù)問題
場景:
- 需要給對象快速擴展額外方法的場景
- 不適合大型繼承結(jié)構(gòu)(復(fù)用性差)
六、寄生組合式繼承(最優(yōu)解)
實現(xiàn)方式:
function inheritPrototype(Child, Parent) { const prototype = Object.create(Parent.prototype); // 創(chuàng)建父類原型的副本 prototype.constructor = Child; // 修復(fù)構(gòu)造函數(shù)指向 Child.prototype = prototype; // 賦值給子類原型 } function Parent(name) { this.name = name; } Parent.prototype.say = function() { return this.name; }; function Child(name) { Parent.call(this, name); // 屬性繼承 } inheritPrototype(Child, Parent); // 方法繼承
特點:
- 只調(diào)用一次父類構(gòu)造函數(shù),避免組合繼承的冗余問題
- 保留完整的原型鏈結(jié)構(gòu)
場景:
- 現(xiàn)代項目推薦的標(biāo)準(zhǔn)繼承方式
- 適用于所有復(fù)雜繼承需求(效率最高)
七、ES6 class 繼承
實現(xiàn)方式:
class Parent { constructor(name) { this.name = name } say() { return this.name } } class Child extends Parent { // extends 關(guān)鍵字 constructor(name) { super(name); // super調(diào)用父類構(gòu)造函數(shù) } } const child = new Child('Child'); child.say(); // 輸出 "Child"
特點:
- 語法糖,本質(zhì)基于原型和寄生組合式繼承
- 支持
static
、super
等特性
場景:
- 現(xiàn)代項目首選方式
- 需要清晰類結(jié)構(gòu)、繼承關(guān)系明確的場景
總結(jié)與場景對比
繼承方式 | 適用場景 | 現(xiàn)代選擇優(yōu)先級 |
---|---|---|
原型鏈繼承 | 快速實現(xiàn)簡單原型鏈(已過時) | ?? |
構(gòu)造函數(shù)繼承 | 需要獨立實例屬性的場景 | ???? |
組合繼承 | 傳統(tǒng)項目兼容性解決方案 | ???? |
寄生組合式繼承 | 需要高效且標(biāo)準(zhǔn)的繼承方案 | ???????? |
ES6 class 繼承 | 現(xiàn)代項目開發(fā)(Babel轉(zhuǎn)譯后兼容性好) | ?????????? |
實際開發(fā)建議:
- 優(yōu)先使用 ES6
class
繼承(清晰、易維護,Babel 轉(zhuǎn)譯后底層使用寄生組合式繼承) - 舊項目維護時根據(jù)現(xiàn)有模式選擇組合或寄生組合繼承
4??原型式/寄生式繼承主要用于對象克隆而非類繼承場景
到此這篇關(guān)于JS 的繼承方式與使用場景的文章就介紹到這了,更多相關(guān)JS 繼承方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript禁制后退鍵(Backspace)實例代碼
這篇文章介紹了javascript禁制后退鍵(Backspace)實例代碼,有需要的朋友可以參考一下2013-11-11layui lay-verify form表單自定義驗證規(guī)則詳解
今天小編就為大家分享一篇layui lay-verify form表單自定義驗證規(guī)則詳解,具有很好的參考價值,相信我對大家有所幫助。一起跟隨小編過來看看吧2019-09-09基于Bootstrap的Metronic框架實現(xiàn)頁面鏈接收藏夾功能
本文給大家介紹基于Metronic的Bootstrap開發(fā)框架實現(xiàn)頁面鏈接收藏夾功能,非常不錯,具有參考借鑒價值,感興趣的朋友一起學(xué)習(xí)吧2016-08-08