bind()的语法是:
fun.bind(thisArg[, arg1[, arg2[, ... ]]]);
thisArg:当绑定函数被调用时,该函数会作为原函数运行时的this指向,当使用new操作符调用绑定函数时,该参数无效。
arg1, arg2... :当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。
返回值:返回由指定的this值和初始化参数改造的原函数拷贝。
bind()使用场景:
1)作为绑定函数使用,并且设置函数的this值。
````
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function() {
return function(){
return this.name;
}
}
}
console.log(object.getNameFunc()());//>The Window
````
getNameFunc()返回一个匿名函数,object.getNameFunc()()立即调用它返回的函数,匿名函数的执行环境具有全局性,因此其this对象通常指向window。
为解决上面方法,我们可以把外部作用域中的this对象保存在闭包函数能够访问到的变量里:
````
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function() {
var _this = this;
return function(){
return _this.name;
}
}
}
console.log(object.getNameFunc()());//>My Object
````
当然也可以bind()方法:
````
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function() {
return function(){
return this.name;
}.bind(this)
}
}
console.log(object.getNameFunc()());//>My Object
````
上面通过bind()方法实现的绑定,效果等价于如下:
````
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function() {
return function(){
return this.name;
}.apply(this)
}
}
console.log(object.getNameFunc());//>My Object
````
2) 偏函数,使一个函数拥有预设的初始值,也称柯里化(currying)
````
var sum = function(x, y) {return x + y;};
var succ = sum.bind(null, 1);//创建一个类似sum的新函数,this值设为null,指向全局变量
//第一个参数绑定到1,新的函数期望只传入一个实参
succ(2);//>3
````
3)配合setTimeout()使用
````
function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
//如果不使用bind()绑定作用域,作用域为winidow
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();
````
4) 作为构造函数的绑定函数,即通过new关键字调用bind()产生的绑定函数,bind()中俄第一个参数(指定this值的参数)不起作用,后续参数正常使用。
````
function Person(_age, _address) {
this.age = _age;
this.address = _address;
console.log(this.name);//undefined
console.log(this.age);//23
}
var north = {
name : "north"
}
var northBind = Person.bind(north, 24);
var northObj = new northBind();
````
name并不是north对象含有的名字,可见第一个参数并没有起作用。
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() {
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 = new fNOP();
return fBound;
};
}
````
看这段代码需要注意的的几个点:
1. bind()返回值是改造参数后的原函数的拷贝,所以调用bind()的必须是函数;
2. 如果返回的函数是一个构造函数,那么this不改变,即不会被传入的第一反应参数重写。
3. fBound函数中对arguments的操作,其实是对bind()函数返回的绑定函数的参数的操作,aArgs和arguments的合并实现了参数预设功能。
4. bind()函数返回的绑定函数与最开始的原函数具有相同的原型
bind()和apply()、call()的区别:
bind()返回一个绑定函数,apply()、call()是立即调用原函数。
备注:可能还是没有完全理解bind吧。。。
参考: