閑聊js1: nodejs中的類定義和繼承的套路

javascript是一門極其靈活的語言。
靈活到你無法忍受!
我個人喜歡強類型的語言,例如c/c++,c#等。
但是js代表著未來,所以需要學(xué)習(xí)。
js中類定義以及繼承有n多種方式,現(xiàn)在來學(xué)習(xí)一下nodejs類定義以及繼承的固定套路。

套路1. 在構(gòu)造函數(shù)(constructor)中總是使用instanceof操作符:

function Base() {
    if (!(this instanceof Base)) {
        return new Base();
    }
}

上述代碼的含義就是: 如果Base這個函數(shù)調(diào)用時沒有使用new操作符,則會自動調(diào)用new操作符,返回Base的實例

套路2. 所有成員變量定義在構(gòu)造函數(shù)(constructor)中

function Base() {
    if (!(this instanceof Base)) {
        return new Base();
    }
    
    //開始成員變量定義
   this.className = "Base";
}

套路3. 所有的成員方法以函數(shù)表達式方式定義在原型(prototype)中【為什么要這樣,其原因在套路4中的inherits源碼注釋中】

Base.prototype.printClassName = function(){
     console.log(this.className);
}

調(diào)用如下:

var base = Base(); //不使用new操作符,直接進行函數(shù)調(diào)用,自動調(diào)用new操作符
console.log(base.className);
base.printClassName();

套路4. 使用util.inherits(子類,父類)進行原型(prototype)繼承

先來看一下inherits的源碼:

var inherits = function(ctor, superCtor) {
    //嚴(yán)格相等測試:undefined/null
    //子類構(gòu)造函數(shù)必須存在
    if (ctor === undefined || ctor === null)
        throw new TypeError('The constructor to "inherits" must not be ' +
            'null or undefined');
    //嚴(yán)格相等測試:undefined/null
    //父類構(gòu)造函數(shù)必須存在
    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');

    //讓子類構(gòu)造函數(shù)對象增加一個super_指針,指向父類,這樣就形成繼承鏈
    ctor.super_ = superCtor;
   
    //調(diào)用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();
    }
}

然后根據(jù)套路4, 調(diào)用inherits函數(shù)進行原型繼承

//注意,inherits調(diào)用不在構(gòu)造函數(shù),也不在原型對象,而是全局調(diào)用
inherits(Child, Base);

最后我們調(diào)用一下child的printClassName方法,該方法在基類原型對象中實現(xiàn)。

子類調(diào)用基類函數(shù)-undefined.png

出現(xiàn)錯誤,child.printClassName()后輸出undefined!
為什么呢?

套路5. 子類的構(gòu)造函數(shù)中使用 父類.call(this),實現(xiàn)父類構(gòu)造函數(shù)中的成員變量繼承

function Child() {
    //老樣子,套路1
    if (!(this instanceof Child)) {
        return new Child();
    }

    //增加這句話,在調(diào)用printClassName就能正常的輸出Base字符串
    Base.call(this);
   
   //如果要更新基類的成員變量,請在Base.call(this)之后!
   this._className = "Child"; //調(diào)用printClassName就能正常的輸出Child字符串
}

Function.prototype.call()

由此可見,nodejs中的繼承需要:
在構(gòu)造函數(shù)中調(diào)用 父類.call(this),實現(xiàn)父類成員變量的繼承
全局調(diào)用inherits(子類,父類) 進行父類成員函數(shù)的繼承

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容