理解JavaScript的Bind(翻譯)

初學(xué)JavaScript時(shí),你可能最不想關(guān)心的就是函數(shù)綁定。不過當(dāng)遇到一個(gè)經(jīng)典問題,如何在另外一個(gè)函數(shù)中保持this指針。這個(gè)時(shí)候,你會(huì)明白Function.prototype.bind()是一個(gè)解決辦法。

第一次遇到這個(gè)問題的時(shí)候,你可能更傾向于通過一個(gè)變量來(lái)持有this,這樣即使更換了函數(shù)的context(上下文),依然可以成功調(diào)用函數(shù)。許多人會(huì)用self,_this,甚至context作為這個(gè)變量名,我常見的是that。這個(gè)方式?jīng)]有問題,不過相比較bind更贊。

我們到底要解決什么問題?

下面一段代碼

var myObj = {

    specialFunction: function () {

    },

    anotherSpecialFunction: function () {

    },

    getAsyncData: function (cb) {
        cb();
    },

    render: function () {
        var that = this;
        this.getAsyncData(function () {
            that.specialFunction();
            that.anotherSpecialFunction();
        });
    }
};

myObj.render();

上面的代碼是正確的,如果直接使用this.specialFunction,函數(shù)已經(jīng)失去了當(dāng)前上下文,然后就會(huì)收到以下錯(cuò)誤

Uncaught TypeError: Object [object global] has no method 'specialFunction'

注意:嚴(yán)格模式,此種情況上下文為undefined

為了能讓specialFunction正常調(diào)用,我們需要保證它在被調(diào)用時(shí)候context是指向的myObj對(duì)象。使用that.specialFunction()能讓我們持有context并正確調(diào)用函數(shù)。

修改部分代碼:

render: function () {

    this.getAsyncData(function () {

        this.specialFunction();

        this.anotherSpecialFunction();

    }.bind(this));

}

剛剛做了什么

bind()會(huì)返回一個(gè)新的函數(shù)。使用時(shí),可以把this作為參數(shù)傳進(jìn)去,那么返回的新函數(shù)就和this綁定在一起了。在結(jié)合上面的代碼,我們傳了this(就是myObj)和函數(shù)綁定在一起,這是我們希望的context。然后等到函數(shù)執(zhí)行的時(shí)候,this就會(huì)指向myObj對(duì)象。
如果對(duì)bind內(nèi)部實(shí)現(xiàn)有興趣,可以看下下面的代碼。

Function.prototype.bind = function (scope) {
    var fn = this;
    return function () {
        return fn.apply(scope);
    };
}

觀察apply的函數(shù)定義,fun.apply(thisArg, [argsArray])它的第一個(gè)參數(shù)就是函數(shù)的上下文。

下面有一個(gè)非常簡(jiǎn)單的bind使用例子

var foo = {
    x: 3
}

var bar = function(){
    console.log(this.x);
}

bar(); // undefined

var boundFunc = bar.bind(foo);

boundFunc(); // 3

如果不調(diào)用bind,bar的context是全局的(global scope),也就是this指針指向的window。綁定完后,bar的this指針指向foo。

瀏覽器支持

瀏覽器 支持版本
Chrome 7
Firefox (Gecko) 4.0(2)
Firefox (Gecko) 4.0(2)
Internet Explorer 9
Opera 11.60
Safari 5.1.4

最后

我沒有逐字逐句進(jìn)行翻譯,其中有些內(nèi)容我按照自己的理解進(jìn)行了略微修改,還有些內(nèi)容我直接跳過。歡迎閱讀原文。
https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容