在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