轉載自:https://www.cnblogs.com/zztt/p/4122352.html
Function.prototype.bind()方法
bind()
方法的主要作用就是將函數綁定至某個對象,bind()
方法會創建一個函數,函數體內this對象的值會被綁定到傳入bind()
函數的值。
例如,在 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!
更普遍的使用情形
再看一個例子:
function f(y,z){ return this.x+y+z; } var m=f.bind({x:1},2); console.log(m(3)); // 6
最后將輸出 6
這是因為 bind()
方法會把傳入它的第一個實參綁定給f函數體內的 this
,從第二個實參起,將依此傳遞給原始函數,因此 {x:1}
傳遞給this
,2
傳遞給形參y
,m(3)
調用時的3
傳遞給形參z
。
其實這個例子 f()
函數能夠處理部分參數,分步計算 ( bind()
時處理了參數x
,和參數y
,調用 m(3)
時處理了參數z
)的過程其實是一個典型的Curry過程(Currying)。
bind()背后的簡單原理
那么bind函數背后做了什么呢? 我們可以用以下代碼來模擬:
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()
函數。