在JavaScript中,bind() 方法夠改變對this的引用,在上下文中創建一個新函數不會被立即執行(對綁定函數的調用,並且可以指定特定的this,成爲一個新的函數,就好像是深拷貝一般),在平常工作中經常用到,並且也是面試的高熱詞彙,這裏就順帶將它進行一些解釋:
語法
fn.bind(thisArg, arg1[, arg2[, ...]]])bind()
方法創建一個新的函數,在 bind()
被調用時,這個新函數的 this
被指定爲 bind()
的第一個參數,而其餘參數將作爲新函數的參數,供調用時使用。當使用new運算符構造,所提供的this將會被忽略,但前置參數仍會提供給模擬函數。當bind()的參數爲空時,this指向全局對象。如瀏覽器中的window。它的返回是一個原函數的拷貝,並擁有指定的 this
值和初始參數。
示例
1、在JavaScript經常犯的一個錯誤是將一個方法從對象中拿出來,然後再調用,期望方法中的 this
是原來的對象(比如在回調中傳入這個方法)。如果不做特殊處理的話,一般會丟失原來的對象。基於這個函數,用原始的對象創建一個綁定函數,巧妙地解決了這個問題:
this.x = 9; // 在瀏覽器中,this 指向全局的 "window" 對象
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 81
var retrieveX = module.getX;
retrieveX();
// 返回 9 - 因爲函數是在全局作用域中調用的
// 創建一個新函數,把 'this' 綁定到 module 對象
// 新手可能會將全局變量 x 與 module 的屬性 x 混淆
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81
2、bind()
能夠使一個函數擁有預設的初始參數(默認值)。只要將這些參數作爲 bind()
的參數寫在 this
後面。當綁定函數被調用時,這些參數會被插入到目標函數的參數列表的開始位置,傳遞給綁定函數的參數會跟在它們後面(也就是說目標函數的參數會優先於調用傳遞的參數)。
function list() {
return Array.prototype.slice.call(arguments);
}
function addArguments(arg1, arg2) {
return arg1 + arg2
}
var list1 = list(1, 2, 3); // [1, 2, 3]
var result1 = addArguments(1, 2); // 3
// 創建一個函數,它擁有預設參數列表。
var leadingThirtysevenList = list.bind(null, 37);
// 創建一個函數,它擁有預設的第一個參數
var addThirtySeven = addArguments.bind(null, 37);
var list2 = leadingThirtysevenList();
// [37]
var list3 = leadingThirtysevenList(1, 2, 3);
// [37, 1, 2, 3]
var result2 = addThirtySeven(5);
// 37 + 5 = 42
var result3 = addThirtySeven(5, 10);
// 37 + 5 = 42 ,第二個參數被忽略
3、在默認情況下,使用 window.setTimeout()
時,this
關鍵字會指向 window
(或 global
)對象。當類的方法中需要 this
指向類的實例時,你可能需要顯式地把 this
綁定到回調函數,就不會丟失該實例的引用。
function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// 在 1 秒鐘後聲明 bloom
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom(); // 一秒鐘後, 調用 'declare' 方法
4、可以通過bind實現一些共有方法。
var fly = function(){
//fly
console.log('I am a ' + this.name + ', I can fly');
};
var bird = {
name: 'bird'
};
var plane = {
name: 'plane'
};
fly.bind(bird)(); //I am a bird, I can fly
fly.bind(plane)();//I am a plane, I can fly
5、針對特定的this調用某些方法。寫起來比較麻煩,這個時候就可以使用bind創建一個shortcut方便調用。
/*你可以用 Array.prototype.slice 來將一個類似於數組的對象(array-like object)轉換成一個真正的數組*/
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.apply.bind(unboundSlice);
// ...
slice(arguments);
參考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind