近期自學JavaScript。學到bind方法這塊兒有些地方不太明確。自己就查了些資料,結合自己的理解寫了這篇文章以備后面回想用。
。
。
事實上應該還是搬磚為主吧。
什么是this對象
先來說說什么是this對象吧。每一個函數在調用的時候都會自己主動獲取兩個特殊變量:this和arguments對象。
this值詳細是指哪個對象是和該函數的運行環境相關的。假設是作為對象的方法,那么this就是對象實例本身;假設是一個全局函數,那么this就是window對象。用一句話來概括,this就是調用這種方法的對象。
保持this上下文
有時候。我們須要保持this的上下文,也就是在一個運行環境中想要訪問到還有一個運行環境的this值。在什么時候須要這么做呢?比方說將一個對象的方法賦值給了一個全局變量,然后在全局變量中調用這種方法,那么this值就不再是原來的對象而是window對象了,然而可能我們仍須要在全局環境中依照對象的方法來調用。又比方說一個方法中包括了閉包,閉包是無法訪問到其外部函數的this對象的,由於this對象是在調用方法的時候自己主動生成,內部函數在搜索這兩個變量的時候僅僅會搜索到其自身的活動對象。而不會沿着作用域鏈往外搜索,所以閉包訪問不到外部函數的this值。
假設要想訪問,就應該想辦法把this值傳遞下去。
通常能夠通過這種方式保持this上下文:在外部函數中將this緩存到一個變量中,通常變量名稱使用self, _this 或者 context。那么閉包就能夠通過這個可訪問的變量來獲取外部函數的this值,this上下文得以保持。比方以下的代碼:
var myObj = {
specialFunction: function () {},
getAsyncData: function (cb) {
cb();
},
render: function () {
var that = this;
this.getAsyncData(function () {
that.specialFunction();
});
}
};
myObj.render();
這里有一個對象myObj。它有一個render實例方法,在這種方法內部又調用了它的還有一個實例方法getAsyncData,而這種方法有一個新的函數作為參數,這個函數相當於是一個閉包。是不能獲取到外部函數中的this值的。為了在這個閉包中也能訪問實例方法,須要獲取到外部環境的this值,這里把this(this為調用render方法的對象。即實例對象myObj)緩存到了變量that中。
此外還可通過bind方法,這就是本文所要講述的重點。
bind方法
bind方法生成了一個新的函數,稱為綁定函數,傳入bind方法的第一個參數作為這個綁定函數的this對象,傳入bind的第二個參數連同后面調用綁定函數時傳入的參數依照先后順序(傳入bind的在前)構成綁定函數的參數。
如今我們把上面的樣例改動一下:
render: function () {
this.getAsyncData(function () {
this.specialFunction();
}.bind(this));
}
.bind()創建了一個函數,當這個函數在被調用的時候。它的 this 關鍵詞會被設置成被傳入的值(這里指調用bind()時傳入的參數)
再看一個bind的使用樣例:
var foo = {
x: 3
}
var bar = function(){
console.log(this.x);
}
bar();
// undefined
var boundFunc = bar.bind(foo);
boundFunc();
// 3
將bar方法和foo對象綁定后,bar中的this對象被替換為了foo,並生成了一個新的函數boundFunc,因此在全局環境中調用boundFunc時。也能夠訪問到foo對象的屬性。
還能夠了解一下Function.prototype.bind()內部是什么樣的:
Function.prototype.bind = function (scope) {
var fn = this;//this是調用bind方法的對象(別的方法對象)
return function () {
return fn.apply(scope);//把fn環境中的this替換為scope
};
}
可看出,bind方法返回了一個新的函數。這種方法返回了原方法(調用bind的方法)通過apply改動作用域(傳入的參數scope)后的運行結果。假設調用這個新函數則會馬上運行fn.apply(scope)。並返回運行后的結果。
fn.bind()
與call、apply的差別
call、apply是改動函數的作用域,而且馬上運行。而bind是返回了一個新的函數,不是馬上運行,即call and apply call a function while bind creates a function。
bind在回調函數中經常使用到。
參考資料:
理解 JavaScript 中的 Function.prototype.bind
js中bind、call、apply函數的使用方法
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind