這樣回答繼承可能面試官更滿意
9021年底了,突然想在這個(gè)最后一個(gè)月準(zhǔn)備一下,試試機(jī)會(huì),能否更進(jìn)一步。所以開始準(zhǔn)備一些基礎(chǔ)知識(shí),也隨帶總結(jié)出來給各位想換工作的同學(xué)。希望大家能找到自己想要的工作。祝大家好運(yùn)!
一、何為繼承
一個(gè)類獲取另一個(gè)或者多個(gè)類的屬性或者方法。繼承可以使得子類具有父類的各種方法和屬性。以免重復(fù)輸出很多代碼。
二、繼承的原理
復(fù)制父類的方法和屬性來重寫子類的原型對(duì)象。
三、原型鏈繼承
3.1 實(shí)現(xiàn)
function Father() { this.text = '1'; } Father.prototype.someFn = function() { console.log(1); } Father.prototype.someValue = '2'; function Son(){ this.text1 = 'text1'; } // 函數(shù)原型指向構(gòu)造函數(shù)的實(shí)例 Son.prototype = new Father();
3.2 優(yōu)點(diǎn)
1、簡(jiǎn)單易操作。
3.3 缺點(diǎn)
1、父類使用this聲明的屬性被所有實(shí)例共享。原因是實(shí)例化是父類一次性賦值到子類實(shí)例的原型上,它會(huì)將父類通過this聲明的屬性也賦值到子類原型上。例如在父類中一個(gè)數(shù)組值,在子類的多個(gè)實(shí)例中,無論哪一個(gè)實(shí)例去修改這個(gè)數(shù)組的值,都會(huì)影響到其他子類實(shí)例。
2、創(chuàng)建子類實(shí)例時(shí),無法向父類構(gòu)造函數(shù)傳參,不夠靈活。
四、借用構(gòu)造函數(shù)(call)
4.1 實(shí)現(xiàn)
function Father(...arr) { this.some = '父類屬性'; this.params = arr; } Father.prototype.someFn = function() { console.log(1); } Father.prototype.someValue = '2'; function Son(fatherParams, ...sonParams) { // Father的this指向Son的this // 使用call調(diào)用父類,F(xiàn)ather將會(huì)立即被執(zhí)行,并且將父類的Father的this執(zhí)行Son // 的this。實(shí)例化子類,this將指向new期間創(chuàng)建的新對(duì)象,返回該新對(duì)象。 Father.call(this, ...fatherParams); this.text = '子類屬性'; this.sonParams = sonParams; } var fatherParams = []; var sonParams = []; var sonInstance = new Son(fatherParams, ...sonParams);
4.2 優(yōu)點(diǎn)
1、可以向父類傳遞參數(shù)。
2、解決父類this聲明的屬性會(huì)被實(shí)例共享的問題。
4.3 缺點(diǎn)
1、只能繼承父類通過this聲明的屬性/方法。不能繼承父類prototype上的屬性/方法。
2、父類方法無法復(fù)用。每次實(shí)例化子類,都要執(zhí)行父類函數(shù)。重新聲明父類所定義的方法,無法復(fù)用。
五、組合繼承(call+new)
原理:通過原型鏈繼承來將this、prototype上的屬性和方法繼承制子類的原型對(duì)象上。使用借用構(gòu)造函數(shù)來繼承父類通過this聲明的屬性和方法在之子類的實(shí)例屬性上。
5.1 實(shí)現(xiàn)
function Father(...arr) { this.some = '父類屬性'; this.params = arr; } Father.prototype.someFn = function() { console.log(1); } Father.prototype.someValue = '2'; function Son(fatherParams, ...sonParams) { // 借用構(gòu)造函數(shù)繼承父類this什么的屬性和方法到子類實(shí)例屬性上 Father.call(this, ...fatherParams); this.text = '子類屬性'; this.sonParams = sonParams; } // 原型鏈繼承,將`this`和`prototype`聲明的屬性/方法繼承至子類的`prototype`上 Son.prototype = new Father('xxxxx'); var fatherParams = []; var sonParams = []; var sonInstance = new Son(fatherParams, ...sonParams);
5.2 優(yōu)點(diǎn)
1、解決原型鏈繼承父類this聲明的屬性或者方法被共享的問題。
2、解決借用構(gòu)造函數(shù)解決不能繼承父類prototype對(duì)象上的屬性/方法問題。
5.3 缺點(diǎn)
1、調(diào)用了父類函數(shù)兩次,造成一定的性能問題。
2、因調(diào)用兩次父類,導(dǎo)出父類通過this聲明的屬性和方法被生成兩份的問題。
3、原型鏈上下文丟失,子類和父類通過prototype聲明的屬性和方法都存在與子類prototype上。
六、原型式繼承
6.1 實(shí)現(xiàn)
function cloneObj(obj) { function F(){}; // 將被繼承的對(duì)象作為空函數(shù)的prototype F.prototype = obj; // 返回new期間創(chuàng)建的新對(duì)象,此對(duì)象的原型為被繼承的對(duì)象, // 通過原型鏈查找可以拿到被繼承對(duì)象的屬性 return new F(); }
6.2 優(yōu)點(diǎn)
1、兼容性好,最簡(jiǎn)單的對(duì)象繼承。
6.3 缺點(diǎn)
1、多少實(shí)例共享被繼承的屬性,存在被篡改的情況,不能傳遞參數(shù)。
七、寄生式繼承(繼承過程封裝)
創(chuàng)建一個(gè)僅用于封裝繼承過程的函數(shù),改函數(shù)在內(nèi)部已某種方式類增強(qiáng)對(duì)象,最后返回對(duì)象。在原型式繼承的基礎(chǔ)上進(jìn)行增強(qiáng)對(duì)象。
7.1 實(shí)現(xiàn)
function createAnother(original){ var clone = cloneObject(original); // 繼承一個(gè)對(duì)象 返回新函數(shù) // do something 以某種方式來增強(qiáng)對(duì)象 clone.some = function(){}; // 方法 clone.obkoro1 = '封裝繼承過程'; // 屬性 return clone; // 返回這個(gè)對(duì)象 }
7.2 優(yōu)點(diǎn)
1、兼容性好,最簡(jiǎn)單的對(duì)象繼承。
7.3 缺點(diǎn)
1、多少實(shí)例共享被繼承的屬性,存在被篡改的情況,不能傳遞參數(shù)。
八、寄生組合式繼承(call+寄生式封裝)
1、使用借用構(gòu)造函數(shù)來繼承父類this聲明的屬性和方法。2、使用寄生式繼承來設(shè)置父類prototype為子類prototype的原型來繼承父類的屬性和方法。
8.1 實(shí)現(xiàn)
function Father(...arr) { this.some = '父類屬性'; this.params = arr; } Father.prototype.someFn = function() { console.log(1); } Father.prototype.someValue = '2'; function Son() { Father.call(this, 'xxxx'); this.text = '2222'; } function inhertPro(son, father){ // 原型式繼承 var fatherPrototype = Object.create(father.prototype); // 設(shè)置Son.prototype的原型是Father.prototype son.prototype = fatherPrototype; // 修正constructor 指向 // constructor的作用:返回創(chuàng)建實(shí)例對(duì)象的Object構(gòu)造函數(shù)的引用。 // 在這里保持constructor指向的一致性 son.prototype.constructor = son; } inhertPro(Son, Father); var sonInstance = new Son();
8.2 優(yōu)點(diǎn)
1、寄生組合式繼承是當(dāng)前最成熟的繼承方法,也是先也常用的繼承方法,在大多數(shù)Js框架中都是用這個(gè)作為繼承方案。
寄生組合式繼承相對(duì)組合繼承的優(yōu)點(diǎn):
1、只調(diào)用了父類構(gòu)造函數(shù)一次,節(jié)約了性能。
2、避免生成了不必要的屬性。
3、使用原型式繼承保證了原型鏈上下文不變,子類的prototype只有子類通過prototype聲明的屬性和方法,父類的prototype只有父類通過prototype聲明的屬性和方法。
九、ES6-extends繼承
9.1 實(shí)現(xiàn)
ES6可以用過extends關(guān)鍵字實(shí)現(xiàn)繼承,這比通過ES5的修改原型鏈實(shí)現(xiàn)繼承,要清晰和方法很多。
class Point{} class ColorPoint extends Point{}
9.2 注意
子類必須在constructor方法中代用super方法,否則新建實(shí)例將會(huì)報(bào)錯(cuò),這是因?yàn)樽宇愖约旱膖his對(duì)象,必須先通過父類的構(gòu)造函數(shù)完成塑性,得到父類的屬性和方法,然后對(duì)其加工,加上子類自己的屬性和方法。如果不調(diào)用super方法,子類將得不到this對(duì)象。如果沒有定義constructor方法,這個(gè)方法會(huì)被默認(rèn)的添加。
9.3 轉(zhuǎn)換
ES6繼承的原理跟寄生組合式繼承是一樣的。優(yōu)缺點(diǎn)也相仿。
把ES6的代碼裝換為ES5 https://www.babeljs.cn/repl
轉(zhuǎn)換前:
class Point{} class ColorPoint extends Point{}
轉(zhuǎn)換后:
轉(zhuǎn)換的結(jié)果核心代碼如下:用于子類的prototype繼承父類的prototype方法。
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
9.4 區(qū)別
ES5的繼承實(shí)質(zhì)是先創(chuàng)建子類的實(shí)例對(duì)象this,然后將父類的方法添加到this上。
ES6的繼承實(shí)質(zhì)是先將父類實(shí)例對(duì)象的方法和屬性加到this上面,然后在用子類的構(gòu)造函數(shù)修改this。
參考
JS基礎(chǔ)-深入淺出繼承
JavaScript高級(jí)程序設(shè)計(jì)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
js 按照指定間隔 向字符串中插入隨機(jī)字符串的實(shí)現(xiàn)代碼
看到論壇有人問,覺得有意思,就試著寫了一下。2010-03-03網(wǎng)站繁簡(jiǎn)切換的JS遇到頁面卡死的解決方法
最近開發(fā)了繁體版本的網(wǎng)站,在網(wǎng)上找了一段比較流行的繁簡(jiǎn)切換的JS實(shí)現(xiàn)了,不過后來卻發(fā)現(xiàn),有些頁面會(huì)卡死,針對(duì)這個(gè)問題,下面有個(gè)不錯(cuò)的解決方法2014-03-03JavaScript實(shí)現(xiàn)點(diǎn)擊自制菜單效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)點(diǎn)擊自制菜單效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02JS+CSS實(shí)現(xiàn)仿新浪微博搜索框的方法
這篇文章主要介紹了JS+CSS實(shí)現(xiàn)仿新浪微博搜索框的方法,實(shí)例分析了javascript針對(duì)搜索框樣式的控制技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02ES6頂層對(duì)象、global對(duì)象實(shí)例分析
這篇文章主要介紹了ES6頂層對(duì)象、global對(duì)象,結(jié)合實(shí)例形式分析了ES6頂層對(duì)象與global對(duì)象的概念、原理、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-06-06微信小程序發(fā)布新版本時(shí)自動(dòng)提示用戶更新的方法
這篇文章主要介紹了微信小程序發(fā)布新版本時(shí)自動(dòng)提示用戶更新的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用小程序具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06webpack開發(fā)環(huán)境和生產(chǎn)環(huán)境的深入理解
這篇文章主要介紹了webpack開發(fā)環(huán)境和生產(chǎn)環(huán)境的深入理解,詳細(xì)的介紹了什么是開發(fā)環(huán)境和生產(chǎn)環(huán)境并配置,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-11-11JavaScript在控件上添加倒計(jì)時(shí)功能的實(shí)現(xiàn)代碼
JavaScript在控件上添加倒計(jì)時(shí)功能,主要原理是利用控件的setEnable(true)/setEnable(false)來進(jìn)行設(shè)置控件的可用與不可用狀態(tài),實(shí)現(xiàn)過程非常簡(jiǎn)單,需要的的朋友參考下吧2017-07-07JavaScript實(shí)現(xiàn)反轉(zhuǎn)字符串的方法詳解
這篇文章主要介紹了JavaScript實(shí)現(xiàn)反轉(zhuǎn)字符串的方法,結(jié)合實(shí)例形式分析了字符串反轉(zhuǎn)操作,并詳細(xì)講述了相關(guān)函數(shù)的功能與使用注意事項(xiàng),需要的朋友可以參考下2017-04-04