bind()方法創建一個新的函數, 當被調用時,將其this關鍵字設置為提供的值,在調用新函數時,在任何提供之前提供一個給定的參數序列。
語法 : fun.bind(thisArg[, arg1[, arg2[, ...]]])
參數含義
this.Arg
當綁定函數被調用時,該參數會作為原函數運行時的 this 指向。當使用[new 操作符],調用綁定函數時,該參數無效。
arg1, arg2, ...
當綁定函數被調用時,這些參數將置于實參之前傳遞給被綁定的方法
返回值:返回由指定的this值和初始化參數改造的原函數拷貝
1.bind() 最簡單的用法是創建一個函數,使這個函數不論怎么調用都有同樣的 this 值。JavaScript新手經常犯的一個錯誤是將一個方法從對象中拿出來,然后再調用,希望方法中的 this 是原來的對象。(比如在回調中傳入這個方法。)如果不做特殊處理的話,一般會丟失原來的對象。從原來的函數和原來的對象創建一個綁定函數,則能很漂亮地解決這個問題:
this.x = 9;
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 返回 81
var retrieveX = module.getX;
retrieveX(); // 返回 9, 在這種情況下,"this"指向全局作用域
// 創建一個新函數,將"this"綁定到module對象
// 新手可能會被全局的x變量和module里的屬性x所迷惑
var boundGetX = retrieveX.bind(module);
boundGetX(); // 返回 81
2.偏函數(Partial Functions)
bind()的另一個最簡單的用法是使一個函數擁有預設的初始參數。這些參數(如果有的話)作為bind()的第二個參數跟在this(或其他對象)后面,之后它們會被插入到目標函數的參數列表的開始位置,傳遞給綁定函數的參數會跟在它們的后面。
function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); // [1, 2, 3]
// Create a function with a preset leading argument
var leadingThirtysevenList = list.bind(undefined, 37);
var list2 = leadingThirtysevenList(); // [37]
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]
3.配合 setTimeout,在默認情況下,this 關鍵字會指向 [window](或全局)對象。當使用類的方法時,需要 this 引用類的實例,你可能需要顯式地把 this綁定到回調函數以便繼續使用實例。
function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
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.作為構造函數使用的綁定函數
自然而然地,綁定函數適用于用new操作符去構造一個由目標函數創建的新的實例。當一個綁定函數是用來構建一個值的,原來提供的 this 就會被忽略。然而, 原先提供的那些參數仍然會被前置到構造函數調用的前面。
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function() {
return this.x + ',' + this.y;
};
var p = new Point(1, 2);
p.toString(); // '1,2'
var emptyObj = {};
var YAxisPoint = Point.bind(emptyObj, 0/*x*/);
// 以下這行代碼在 polyfill 不支持,
// 在原生的bind方法運行沒問題:
//(譯注:polyfill的bind方法如果加上把bind的第一個參數,即新綁定的this執行Object()來包裝為對象,Object(null)則是{},那么也可以支持)
var YAxisPoint = Point.bind(null, 0/*x*/);
var axisPoint = new YAxisPoint(5);
axisPoint.toString(); // '0,5'
axisPoint instanceof Point; // true
axisPoint instanceof YAxisPoint; // true
new Point(17, 42) instanceof YAxisPoint; // true
你知道不需要做特別的處理就可以用new操作符創建一個綁定函數。必然地,你需要知道不需要做特別處理就可以創建一個可以被直接調用的綁定函數,即使你更希望綁定函數是用new操作符來調用。
// 這個例子可以直接在你的 javascript 控制臺運行
// ...接著上面的代碼繼續(譯注:
// 仍然能作為一個普通函數來調用
// (即使通常來說這個不是被期望發生的)
YAxisPoint(13);
emptyObj.x + ',' + emptyObj.y; // '0,13'
5.如果你希望一個綁定函數只支持使用new操作符或者只能直接調用它,那么模板函數必須強制執行那限制。
快捷調用,在你想要為一個需要特定的 this 值的函數創建一個捷徑(shortcut)的時候,bind()方法也很好用。你可以用 [Array.prototype.slice] 來將一個類似于數組的對象(array-like object)轉換成一個真正的數組,就拿它來舉例子吧。你可以創建這樣一個捷徑:
var slice = Array.prototype.slice;
// ...
slice.apply(arguments);
用 bind() 可以使這個過程變得簡單。在下面這段代碼里面,slice是 [Function.prototype]的 [call()] 方法的綁定函數,并且將 [Array.prototype] 的 [slice()] 方法作為 this的值。這意味著我們壓根兒用不著上面那個 apply() 調用了。
// same as "slice" in the previous example
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundSlice);
// ...
slice(arguments);
原文地址(https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)