淺析 JavaScript 中的 Function.prototype.bind() 方法

Function.prototype.bind()方法

bind() 方法的主要做用就是將函數綁定至某個對象,bind() 方法會建立一個函數,函數體內this對象的值會被綁定到傳入bind() 函數的值。app

例如,在 f() 函數上調用 bind() 方法並傳入參數 obj ,即 f.bind(obj) ,這將返回一個新函數, 新函數會把原始的函數 f() 當作 obj 的方法來調用,就像 obj.f() 似的,固然這時 f() 函數中的 this 對象指向的是 obj函數

簡單使用情形一

var o={
    f: function () {
        var self=this;
        var fff=function() {
            console.log(self.value);  //此時 this 指向的是全局做用域 global/window,所以須要使用 self 指向對象o
        };
        fff();
    },
    value: "Hello World!"
};
o.f(); // Hello World!

上例是咱們經常使用了 保持 this 上下文的方法,把 this 賦值給了中間變量 self,這樣在內部嵌套的函數中可以使用 self 訪問到對象o,不然仍使用 this.value,內部嵌套函數的this此時指向的是全局做用域,最後的輸出將會是 undefined,代碼以下:學習

var o={
    f: function () {
        var self=this;
        var fff=function() {
            console.log(this.value); 
        };
        fff();
    },
    value: "Hello World!"
};
o.f(); // undefined

可是,若是咱們使用 bind()函數,將fff函數的綁定在對象o中,即將fff()函數內部的 this 對象綁定爲對象 o,那麼能夠碰見此時 this.value 是存在的。代碼以下:測試

var o={
    f: function () {
        var self=this;
        var fff=function() {
            console.log(this.value); // bind(this) 中 this 指向的是o,這裏也可直接寫成 bind(o)
        }.bind(this);
        fff();
    },
    value: "Hello World!"
};
o.f(); // Hello World!

更廣泛的使用情形

再看一個例子:this

function f(y,z){
    return this.x+y+z;
}
var m=f.bind({x:1},2); 
console.log(m(3));  // 6

最後將輸出 6prototype

這是由於 bind()方法會把傳入它的第一個實參綁定給f函數體內的 this,從第二個實參起,將依此傳遞給原始函數,所以 {x:1}傳遞給this ,2傳遞給形參ym(3) 調用時的3 傳遞給形參zcode

其實這個例子 f() 函數可以處理部分參數,分步計算 ( bind() 時處理了參數x,和參數y,調用 m(3)時處理了參數z )的過程實際上是一個典型的Curry過程(Currying)。對象

bind()背後的簡單原理

那麼bind函數背後作了什麼呢? 咱們能夠用如下代碼來模擬:ip

Function.prototype.testBind = function (scope) {
    var fn = this;                                // this 指向的是調用testBind方法的一個函數
    return function () {
        return fn.apply(scope, arguments);
    }
};

下面是測試的例子:作用域

var foo = {x: "Foo "};
var bar = function (str) {
    console.log(this.x+(arguments.length===0?'':str));
};

bar();                                   // undefined

var testBindBar = bar.testBind(foo);     // 綁定 foo
testBindBar("Bar!");                     // Foo Bar!

當調用 testBind() 後,咱們建立了一個新的函數,經過調用 applythis 設置成 foo, OK,如今應該比較清晰了,但實際 bind() 的實現遠比上面的複雜,如上面提到的 curry化過程等,上面只是主要原理便於學習理解 bind() 函數。

參考資料: Javascript權威指南

相關文章
相關標籤/搜索