javascript是一門極其靈活的語言。
靈活到你無法忍受!
我個人喜歡強類型的語言,例如c/c++,c#等。
但是js代表著未來,所以需要學習。
js中類定義以及繼承有n多種方式,現在來學習一下nodejs類定義以及繼承的固定套路。
套路1. 在構造函數(constructor)中總是使用instanceof操作符:
function Base() { if (!(this instanceof Base)) { return new Base(); } }
上述代碼的含義就是: 如果Base這個函數調用時沒有使用new操作符,則會自動調用new操作符,返回Base的實例
套路2. 所有成員變量定義在構造函數(constructor)中
function Base() { if (!(this instanceof Base)) { return new Base(); } //開始成員變量定義 this.className = "Base"; }
套路3. 所有的成員方法以函數表達式方式定義在原型(prototype)中【為什么要這樣,其原因在套路4中的inherits源碼注釋中】
Base.prototype.printClassName = function(){ console.log(this.className); }
調用如下:
var base = Base(); //不使用new操作符,直接進行函數調用,自動調用new操作符 console.log(base.className); base.printClassName();
套路4. 使用util.inherits(子類,父類)進行原型(prototype)繼承
先來看一下inherits的源碼:
var inherits = function(ctor, superCtor) { //嚴格相等測試:undefined/null //子類構造函數必須存在 if (ctor === undefined || ctor === null) throw new TypeError('The constructor to "inherits" must not be ' + 'null or undefined'); //嚴格相等測試:undefined/null //父類構造函數必須存在 if (superCtor === undefined || superCtor === null) throw new TypeError('The super constructor to "inherits" must not ' + 'be null or undefined'); //要點: 如果要繼承的話,父類必須要有prototype對象 //這也是為什么將所有成員方法都定義在prototype對象中!!! if (superCtor.prototype === undefined) throw new TypeError('The super constructor to "inherits" must ' + 'have a prototype'); //讓子類構造函數對象增加一個super_指針,指向父類,這樣就形成繼承鏈 ctor.super_ = superCtor; //調用Object.setPrototypeOf(子類的prototype,父類的prototype) Object.setPrototypeOf(ctor.prototype, superCtor.prototype); };
Object.setPrototypeOf : 該鏈接可以了解一下setPrototypeOf方法,非常簡單,其Polyfill如下:
// 僅適用于Chrome和FireFox,在IE中不工作: Object.setPrototypeOf = Object.setPrototypeOf || function (obj, proto) { obj.__proto__ = proto; return obj; }
我們來測試一下繼承。
先定義子類
function Child() { //老樣子,套路1 if (!(this instanceof Child)) { return new Child(); } }
然后根據套路4, 調用inherits函數進行原型繼承
//注意,inherits調用不在構造函數,也不在原型對象,而是全局調用 inherits(Child, Base);
最后我們調用一下child的printClassName方法,該方法在基類原型對象中實現。
子類調用基類函數-undefined.png
出現錯誤,child.printClassName()后輸出undefined!
為什么呢?
套路5. 子類的構造函數中使用 父類.call(this),實現父類構造函數中的成員變量繼承
function Child() { //老樣子,套路1 if (!(this instanceof Child)) { return new Child(); } //增加這句話,在調用printClassName就能正常的
Function.prototype.call()
由此可見,nodejs中的繼承需要:
在構造函數中調用 父類.call(this),實現父類成員變量的繼承
全局調用inherits(子類,父類) 進行父類成員函數的繼承
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com