理解bind方法使用與實現
阿新 • • 發佈:2018-07-23
reset eof 另一個 構建 問題 tostring 瀏覽器 property this指向
方法描述
bind()方法創建一個新函數,當被調用時,將其this關鍵字設置為提供的值。
語法說明
fn.bind(thisArg,arg1,arg2,..)
參數說明
thisArg:當綁定函數被調用時,該參數會作為原函數運行時的this指向。當使用new操作符調用綁定函數時,該參數無效。
arg1,arg2,…:當綁定函數被調用時,這些參數將傳遞給被綁定的方法。
應用場景
1、創建綁定方法
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、偏函數
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
在默認情況下,使用window.setTimeout()時,this關鍵字會指向window(或全局)對象。當使用類的方法時,需要this引用類的實例,需要顯式地把this綁定到回調函數以便繼續使用實例。
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
Polyfill
bind()函數在 ECMA-262 第五版才被加入;它可能無法在所有瀏覽器上運行。你可以部份地在腳本開頭加入以下代碼,就能使它運作,讓不支持的瀏覽器也能使用 bind() 功能。
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== 'function') {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function() {},
fBound = function() {
// this instanceof fNOP === true時,說明返回的fBound被當做new的構造函數調用
return fToBind.apply(this instanceof fNOP
? this
: oThis,
// 獲取調用時(fBound)的傳參.bind 返回的函數入參往往是這麽傳遞的
aArgs.concat(Array.prototype.slice.call(arguments)));
};
// 維護原型關系
if (this.prototype) {
// Function.prototype doesn't have a prototype property
fNOP.prototype = this.prototype;
}
// 下行的代碼使fBound.prototype是fNOP的實例,因此
// 返回的fBound若作為new的構造函數,new生成的新對象作為this傳入fBound,新對象的__proto__就是fNOP的實例
fBound.prototype = new fNOP();
return fBound;
};
}
原文連接
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
理解bind方法使用與實現