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
傳遞給形參y
,m(3)
調用時的3
傳遞給形參z
。code
其實這個例子 f()
函數可以處理部分參數,分步計算 ( bind()
時處理了參數x
,和參數y
,調用 m(3)
時處理了參數z
)的過程實際上是一個典型的Curry過程(Currying)。對象
那麼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()
後,咱們建立了一個新的函數,經過調用 apply
將 this
設置成 foo
, OK,如今應該比較清晰了,但實際 bind()
的實現遠比上面的複雜,如上面提到的 curry化過程等,上面只是主要原理便於學習理解 bind()
函數。
參考資料: Javascript權威指南