摘要:參考文章多層繼承方法參考文章中提供了一個(gè)思路不一定要是一個(gè)變量也可以是一個(gè)函數(shù)只要它能返回我們期望的父級(jí)對(duì)象就可以了下面是我對(duì)它給出的源碼的一些修改和注釋另外有個(gè)測(cè)試示例要想擁有方法必須繼承類注意方法中不要再在時(shí)為子類添加指向父類本身的屬
參考文章
js多層繼承 super方法
參考文章1中提供了一個(gè)思路, _super不一定要是一個(gè)變量, 也可以是一個(gè)函數(shù), 只要它能返回我們期望的父級(jí)對(duì)象就可以了. 下面是我對(duì)它給出的源碼的一些修改和注釋, 另外有3個(gè)測(cè)試示例.
/* * @author: general * @github: https://gist.github.com/generals-space/a75cfca06e1f8d463022e0e02446c363 */ /* * 要想擁有_super()方法, 必須繼承SuperExtend類. * 注意: * 1. inherits方法中不要再在assign時(shí)為子類添加指向父類本身的屬性了, 會(huì)出問(wèn)題的. * 2. 當(dāng)需要使用_super()方法調(diào)用父類的某個(gè)方法時(shí), 必須要保證子類有同名方法, 需要通過(guò)子類的方法調(diào)用父類方法才行 */ function SuperExtend(){} SuperExtend.prototype._super = function(){ // caller調(diào)用者應(yīng)該會(huì)是子類的成員方法對(duì)象, 或是子類構(gòu)造函數(shù)本身 var caller = arguments.callee.caller; // 這里先得到this所屬的構(gòu)造函數(shù)類 var chain = this.constructor; var parent = null; // 沿繼承鏈一直向上遍歷, 至少要遍歷到SuperExtend的第一個(gè)子類 // 目標(biāo)是**找到主調(diào)函數(shù)到底屬于繼承鏈上的哪一層級(jí), 然后才能得到這個(gè)調(diào)用者的父類, 也就是我們需要的super對(duì)象** while(chain && chain.prototype){ // 對(duì)象的隱式原型`__proto__`屬性是一個(gè)指針, 它指向**構(gòu)造本對(duì)象的**, **構(gòu)造函數(shù)類**, **的原型**. // 但是由于inherits的自定義繼承機(jī)制, chain.__proto__指向的是父級(jí)構(gòu)造函數(shù)類(chain本身為子級(jí)構(gòu)造函數(shù)類) parent = chain.__proto__; // 如果調(diào)用者正好是構(gòu)造函數(shù)類本身, 說(shuō)明是在構(gòu)造函數(shù)類的函數(shù)體中調(diào)用的, // 直接返回父級(jí)構(gòu)造函數(shù)類本身 if(caller == chain) return parent; // 如果調(diào)用者不是子級(jí)構(gòu)造函數(shù)類, 就應(yīng)該是原型中的方法了. var props = Object.getOwnPropertyNames(chain.prototype); for(var i = 0; i < props.length; i ++){ // 這里雖然相等, 但有可能是當(dāng)前類從上一層父類繼承而來(lái)的屬性, 而當(dāng)前類本身并沒(méi)有定義過(guò)這個(gè)方法. // 需要進(jìn)一步確認(rèn), 即確認(rèn)父類原型上沒(méi)有與它完全相同的方法(當(dāng)然, 方法名可能一樣). if(caller == chain.prototype[props[i]] && caller != parent.prototype[props[i]]){ return parent.prototype; } } chain = parent; } return chain; }; /* * function: 自定義通用繼承方法. * 使用方法: inherits(子類, 父類) */ function inherits(subClass, superClass){ Object.assign(subClass.prototype, superClass.prototype, { constructor: subClass, }); // 建立這種聯(lián)系后, 相當(dāng)于subClass成了superClass的實(shí)例了 // 基本等價(jià)于subClass.prototype = superClass Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
3個(gè)測(cè)試示例如下
測(cè)試用例1. 基本測(cè)試// 測(cè)試用例1. 基本測(cè)試 function A(a){ this.a = a; } inherits(A, SuperExtend); A.prototype.sayHi = function(){ console.log(this.a); }; function B(a, b){ this._super().call(this, a); this.b = b; } inherits(B, A); B.prototype.sayHi = function(){ this._super().sayHi.call(this); console.log(this.a, this.b); }; function C(a, b, c){ // 這里得到的是父級(jí)構(gòu)造函數(shù)類本身, 直接call調(diào)用即可 this._super().call(this, a, b); this.c = c; } inherits(C, B); C.prototype.sayHi = function(){ // 這里得到的是父級(jí)構(gòu)造函數(shù)類的原型對(duì)象 this._super().sayHi.call(this); console.log(this.a, this.b, this.c); }; var c = new C(2, 5, 8); c.sayHi();測(cè)試用例2. 驗(yàn)證同層級(jí)函數(shù)間調(diào)用的情況
// 測(cè)試用例2. 驗(yàn)證同層級(jí)函數(shù)間調(diào)用的情況 function A(a){ this.a = a; } inherits(A, SuperExtend); A.prototype.sayA = function(){ this.sayB(); }; A.prototype.sayB = function(){ console.log(this.a); }; function B(a, b){ this._super().call(this, a); this.b = b; } inherits(B, A); B.prototype.sayB = function(){ this._super().sayB.call(this); console.log(this.a, this.b); }; function C(a, b, c){ // 這里得到的是父級(jí)構(gòu)造函數(shù)類本身, 直接call調(diào)用即可 this._super().call(this, a, b); this.c = c; } inherits(C, B); var c = new C(2, 5, 8); c.sayA();測(cè)試用例3. 驗(yàn)證主調(diào)函數(shù)與被調(diào)函數(shù)不同名的情況
// 測(cè)試用例3. 驗(yàn)證主調(diào)函數(shù)與被調(diào)函數(shù)不同名的情況 function A(a){ this.a = a; } inherits(A, SuperExtend); A.prototype.sayA = function(){ console.log(this.a); }; function B(a, b){ this._super().call(this, a); this.b = b; } inherits(B, A); B.prototype.sayB = function(){ this._super().sayA.call(this); console.log(this.a, this.b); }; function C(a, b, c){ // 這里得到的是父級(jí)構(gòu)造函數(shù)類本身, 直接call調(diào)用即可 this._super().call(this, a, b); this.c = c; } inherits(C, B); var c = new C(2, 5, 8); c.sayB();
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/92862.html
摘要:參考文章多層繼承方法本系列文章對(duì)實(shí)現(xiàn)多級(jí)繼承做一個(gè)學(xué)習(xí)和探究第三篇給出最終的模擬代碼及測(cè)試用例簡(jiǎn)單的父子繼承父類子類原型鏈繼承這里我用了關(guān)鍵字表示了繼承的父類方法可以將其附加到子類實(shí)例對(duì)象上用起來(lái)會(huì)方便一點(diǎn)但是比較致命的一點(diǎn)是這種方式不適 參考文章 js多層繼承 super方法 本系列文章對(duì)js es5實(shí)現(xiàn)多級(jí)繼承做一個(gè)學(xué)習(xí)和探究, 第三篇給出最終的模擬代碼及測(cè)試用例. 簡(jiǎn)單的父-子繼...
摘要:參考文章官網(wǎng)是一個(gè)的編譯器它可以將的代碼轉(zhuǎn)換成等價(jià)的我們看看它是怎么模擬關(guān)鍵字的與上面等價(jià)的語(yǔ)句如下貌似不支持多重繼承啊覆寫子類的對(duì)象設(shè)置隱式原型感覺這樣很怪因?yàn)檫@樣意為著子類將成為父類的實(shí)例對(duì)象呃類似的概念但我不覺得父子類關(guān)系與類和實(shí) 參考文章 Babel官網(wǎng) babel是一個(gè)es6->es5的編譯器, 它可以將es6的代碼轉(zhuǎn)換成等價(jià)的es5. 我們看看它是怎么模擬super關(guān)鍵字的...
摘要:歡迎關(guān)注我的博客正文讓我來(lái)構(gòu)造函數(shù)其實(shí),模擬一個(gè)類的方式非常的簡(jiǎn)單構(gòu)造函數(shù)。我們先來(lái)看一個(gè)例子這里通過(guò)構(gòu)造函數(shù)模擬出來(lái)的類,其實(shí)和其他語(yǔ)言的類行為上是基本一致的,唯一的區(qū)別就是它不具備私有方法。 前言 ES6時(shí)代的來(lái)臨,使得類繼承變得如此的圓滑。但是,你有思考過(guò)ES6的類繼承模式嗎?如何去實(shí)現(xiàn)它呢? 類繼承對(duì)于JavaScript來(lái)說(shuō),實(shí)現(xiàn)方式與Java等類語(yǔ)言大不相同。熟悉JavaS...
摘要:接下來(lái)我們看下類的寫法,這個(gè)就很接近于傳統(tǒng)面向?qū)ο笳Z(yǔ)言了。如果你想了解傳統(tǒng)面向?qū)ο笳Z(yǔ)言,這里是一個(gè)好切入點(diǎn)。作為對(duì)象時(shí),指向父類的原型對(duì)象。這些就是為將來(lái)在中支持面向?qū)ο蟮念悪C(jī)制而預(yù)留的。 在ES5中,我們經(jīng)常使用方法或者對(duì)象去模擬類的使用,并基于原型實(shí)現(xiàn)繼承,雖然可以實(shí)現(xiàn)功能,但是代碼并不優(yōu)雅,很多人還是傾向于用 class 來(lái)組織代碼,很多類庫(kù)、框架創(chuàng)造了自己的 API 來(lái)實(shí)現(xiàn) c...
摘要:父類中的訪問(wèn)權(quán)限一定要小于或者等于子類訪問(wèn)權(quán)限的個(gè)關(guān)鍵字訪問(wèn)權(quán)限大小,其中為默認(rèn)值,不用寫。下面是一個(gè)典型的代碼父類代碼子類代碼測(cè)試類代碼輸出結(jié)果在子類那里已經(jīng)表明。 繼承(Extends)1、前言還是先說(shuō)一下博主本人的一些基本情況吧。本人去年剛剛畢業(yè),專業(yè)是電氣工程及其自動(dòng)化,就是在大學(xué)期間完全沒(méi)有接觸過(guò)JAVA,也就稍稍了解了一下C語(yǔ)言。后來(lái)找了現(xiàn)在的工作也是和編程沒(méi)有任何關(guān)系,是...
閱讀 3013·2019-08-30 15:55
閱讀 2961·2019-08-30 15:53
閱讀 2404·2019-08-26 13:47
閱讀 2718·2019-08-26 13:43
閱讀 3268·2019-08-26 13:33
閱讀 2925·2019-08-26 11:53
閱讀 1889·2019-08-23 18:35
閱讀 927·2019-08-23 17:16