深入理解javascript系列(十五):高階函式

小旋風柴進發表於2018-06-13

我們都學過javascript的物件導向,在我學習的過程中,一度有個問題困擾著我,那就是在建構函式中,如果使用了this,那麼這個this指向的是誰?如果在定義的原型方法中使用了this,那麼這個this又指向誰了?是建構函式、原型、還是例項?到底是誰在決定?

function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.getName = function() {
    return this.name;
}
var p1 = new Person(`pan`, 18);
p1.getName();複製程式碼

建構函式其實就是普通的函式,而this是在函式執行時才確定的。那麼是什麼導致建構函式變得如此特別了?

與new 關鍵字有關

如果我們自定義一個New方法,來模擬關鍵字new的能力,那麼會有如下實現(在此之前請先回憶一下new 一個函式 會發生什麼.,如果您沒有想起來,那就記住new一個函式,生成一個例項物件)。

//將建構函式以引數形式傳入
function New(func) {
    //宣告一箇中間物件,該物件為最終返回的例項

    var res = {};
    if(func.prototype !== null) {
        //將例項的原型指向建構函式的原型
        res.__proto__ = func.prototype;
    }

    //ret為建構函式執行的結果,這裡通過apply,
    //將建構函式內部的this指向修改為指向res,即為例項物件

    var ret = func.apply(res, Array.prototype.slice.call(arguments,1))

    //當在建構函式中明確指定了返回物件時,那麼new的執行結果就是該返回物件
    if((typeof ret === `object` || typeof ret === `function`) && ret !== null) {
        return ret;
    }

    //如果沒有明確指定返回物件,則預設返回res,這個res就是例項物件
    return res;
}複製程式碼

為了方便大家理解,例子中做了一些註解。通過New 方法的實現可以看出,執行時,利用apply設定了傳入的建構函式的this指向,因此當使用New方法建立例項時,建構函式中的this就指向了被建立的例項。

如果把當前函式看成基礎函式,那麼高階函式,就是讓當前函式獲得額外能力的函式。如果把建構函式看成基礎函式,那麼New方法,就是建構函式的高階函式。建構函式本就和普通函式一樣,沒有什麼區別。但是因為New的存在,它獲得了額外的能力。New方法每次執行都會建立一個新的中間物件,並將中間物件的原型指向建構函式的原型,將建構函式的this指向該中間物件。這樣統一邏輯的封裝,就是高階函式的運用。

當然,如果簡單粗暴一點來理解,則凡是接收一個函式作為引數的函式,就是高階函式。但是如果這樣理解,那麼我們還是用不好高階函式。因為正如陽波大神所說,高階函式其實是一個高度封裝的過程,理解它需要點想象力。那麼在接下來的系列中,就藉助幾個例子,來理解高階函式的封裝。

原文釋出時間為:2018年06月17日
原文作者:Panthon
本文來源掘金如需轉載請聯絡原作者


相關文章