bind() 方法 :
bind方法本身和 apply 、call很类似, 也同样是改变this指向的方法, 但是bind使用的地方与apply 和 call 有些不同.
注意 :
bind方法会创建一个新函数, 称作绑定函数, 当调用bind函数时, 为以第一个参数为this(通常传入的也是this), 传入bind的第二个以及以后的参数加上绑定函数运行时本身的参数, 按照顺序作为原函数的参数来调用函数.
在具体实例中, 我们通常用self、that等, 用来保存this, 例如 :
var foo = {
num: 1,
eventBind: function(){
var self = this;
$('.someClass').on('click',function(event) {
console.log(self.num); //1
});
}
}
由于 Javascript 特有的机制,上下文环境在 eventBind:function(){ } 过渡到 $(‘.someClass’).on(‘click’,function(event) { }) 发生了改变,上述使用变量保存 this 这些方式都是有用的,也没有什么问题。当然使用 bind() 可以更加优雅的解决这个问题:
var foo = {
bar : 1,
eventBind: function(){
$('.someClass').on('click',function(event) {
console.log(this.bar); //1
}.bind(this));
}
}
在上述代码里,bind() 创建了一个函数,当这个click事件绑定在被调用的时候,它的 this 被传入(调用bind()时传入的参数)。因此,这里我们传入想要的上下文 this( foo ),到 bind() 函数中。然后,当回调函数被执行的时候, this 便指向 foo 对象。
例如:
var bar = function(){
console.log(this.x);
}
var foo = {
x:3
}
bar(); // undefined
var func = bar.bind(foo);
func(); // 3
这里我们创建了一个新的函数 func,当使用 bind() 创建一个绑定函数之后,它被执行的时候,它的 this 会被设置成 foo , 而不是像我们调用 bar() 时的全局作用域。
有个有趣的问题,如果连续 bind() 两次,亦或者是连续 bind() 三次那么输出的值是什么呢?像这样:
var bar = function(){
console.log(this.x);
}
var foo = {
x:3
}
var sed = {
x:4
}
var func = bar.bind(foo).bind(sed);
func(); //?
var fiv = {
x:5
}
var func = bar.bind(foo).bind(sed).bind(fiv);
func(); //?
答案是,两次都仍将输出 3 ,而非期待中的 4 和 5 。原因是,在Javascript中,多次 bind() 是无效的。更深层次的原因, bind() 的实现,相当于使用函数在内部包了一个 call / apply ,第二次 bind() 相当于再包住第一次 bind() ,故第二次以后的 bind 是无法生效的。
Apply 、Call 、 Bind 比较
那么 apply、call、bind 三者相比较,之间又有什么异同呢?何时使用 apply、call,何时使用 bind 呢。简单的一个例子:
var A = {
name : "A",
}
var B = {
name : "B",
getName : function(){
console.log(this.name);
},
}
B.getName.bind(A)(); //A
B.getName.call(A); //A
B.getName.apply(A); //A
三个输出的都是A,但是注意看使用 bind() 方法的,他后面多了对括号。
也就是说,区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。
总结:
apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
apply 、 call 、bind 三者都可以利用后续参数传参;
bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。