首页 > 代码库 > apply,call,bind的区别

apply,call,bind的区别

apply和call

在js中,apply,call,bind都是为了改变函数的执行上下文的而存在的,即改变函数内部this的指向。

下面的例子可以说明我们为什么要用apply和call,以及apply和call的区别。

function Person(){};
Person.prototype = {
  name:‘John‘,
  sayName:function(type){
    console.log(this.name + " "+ type);
  }
}
var testPerson = new Person();

var lily = {name: ‘lily‘};  

testPerson.sayName(‘prototype‘); // John prototype

testPerson.sayName.call(lily,‘call‘); //lily call

testPerson.sayName.apply(lily,[‘apply‘]); // lily apply

上面的代码输出结果如下图所示:

技术分享

 

(1)可以看出 call 和 apply是为了动态改变this而出现的,testPerson.sayName(‘prototype‘) 中没有指定一个this,所以直接用了还是内部的this,而在 testPerson.sayName.call(lily,‘call‘) 和 testPerson.sayName.apply(lily,[‘apply‘]) 已经有了外部的lily,所以用了lily对象的this,而不是函数内部的this。因此call和apply是用来改变还是内部this的指向的。

(2)注意一下在用call和apply的时候,这两个方法接受参数方式的区别

func.call(this, args1, args2,....)

func.apply(this, [args1, args2,...]);

call是将所有参数通过args全部列出来,而apply是将参数存在数组里,所以在知道函数的参数个数是,二者是没有什么区别的。但是如果函数的参数个数不定时,就需要用apply,通过数组的push,将参数传进数组,然后调用。在参数个数不定的时候,在函数内部也可以通过arguments将这个数组遍历出来。

 

bind

 关于bind的用法和apply/call 差不多,在MDN上的解释就是:bind()会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入bind()方法的第一个参数作为this,传入bind()方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。

var bar = function(){
console.log(this.x);
}
var foo = {
x:3
};
bar(); //undefined,函数本身和全部作用域中都找不到x,所以输出undefined
var func = bar.bind(foo);
func(); // 3

在执行bind()创建一个绑定函数之后,在它被执行时,this会被设置成foo,而不是全部作用域。

还有一点需要注意的是,在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);
上面这段代码不会输出意料中的4,5,而是输出3,说明多次bind()是无效的。
 
bind/call/apply区别
 

function Person(){};
Person.prototype = {
  name:‘John‘,
  sayName:function(type){
    console.log(this.name + " "+ type);
  }
}
var testPerson = new Person();

var lily = {name: ‘lily‘};  

testPerson.sayName(‘prototype‘); // John prototype

testPerson.sayName.call(lily,‘call‘); //lily call

testPerson.sayName.apply(lily,[‘apply‘]); // lily apply

testPerson.sayName.bind(lily,[‘bind‘])(); //lily bind

上面的代码在很容易发现在用bind的时候,后面多了一个(),这个()表示立即执行

说明bind()改变执行上下文之后不是立即执行的,而apply/call是立即执行的。

总结:

  • apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
  • apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
  • apply 、 call 、bind 三者都可以利用后续参数传参;
  • bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

 

apply,call,bind的区别