在JavaScript中,call
、apply
和bind
是Function
对象自带的三个方法,这三个方法的主要做用是改变函数中的this
指向。javascript
call
、apply
、bind
方法的共同点和区别:apply
、 call
、bind
三者都是用来改变函数的this对象的指向的;apply
、 call
、bind
三者第一个参数都是this要指向的对象,也就是想指定的上下文(函数的每次调用都会拥有一个特殊值——本次调用的上下文(context)——这就是this
关键字的值。);apply
、 call
、bind
三者均可以利用后续参数传参;bind
是返回对应函数,便于稍后调用;apply
、call
则是当即调用 。java
1、call数组
call()
语法:app
call([thisObj[,arg1[, arg2[, [,.argN]]]]])复制代码
定义:调用一个对象的一个方法,以另外一个对象替换当前对象。函数
说明: call
方法能够用来代替另外一个对象调用一个方法。call
方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。ui
thisObj
的取值有如下4种状况:
(1) 不传,或者传null,undefined, 函数中的this指向window对象
(2) 传递另外一个函数的函数名,函数中的this指向这个函数的引用
(3) 传递字符串、数值或布尔类型等基础类型,函数中的this指向其对应的包装对象,如 String、Number、Boolean
(4) 传递一个对象,函数中的this指向这个对象this
function a(){
console.log(this); //输出函数a中的this对象
}
function b(){}
var c={name:"call"}; //定义对象c
a.call(); //window
a.call(null); //window
a.call(undefined); //window
a.call(1); //Number
a.call(''); //String
a.call(true); //Boolean
a.call(b); //function b(){}
a.call(c); //Object复制代码
若是你不理解上面的,不要紧,咱们再来看一个例子:spa
function class1(){
this.name=function(){
console.log("我是class1内的方法");
}
}
function class2(){
class1.call(this); //此行代码执行后,当前的this指向了class1(也能够说class2继承了class1)
}
var f=new class2();
f.name(); //调用的是class1内的方法,将class1的name方法交给class2使用复制代码
经常使用例子:
(1)code
function eat(x,y){
console.log(x+y);
}
function drink(x,y){
console.log(x-y);
}
eat.call(drink,3,2);
输出:5复制代码
这个例子中的意思就是用 eat 来替换 drink,eat.call(drink,3,2) == eat(3,2) ,因此运行结果为:console.log(5);
注意:js 中的函数实际上是对象,函数名是对 Function 对象的引用。对象
(2)
function Animal(){
this.name="animal";
this.showName=function(){
console.log(this.name);
}
}
function Dog(){
this.name="dog";
}
var animal=new Animal();
var dog=new Dog();
animal.showName.call(dog);
输出:dog复制代码
在上面的代码中,咱们能够看到Dog里并无showName方法,那为何(this.name)的值是dog呢?
关键就在于最后一段代码(animal.showName.call(dog)),意思是把animal的方法放到dog上执行,也能够说,把animal 的showName()方法放到 dog上来执行,因此this.name 应该是 dog。
(3)继承
function Animal(name){
this.name=name;
this.showName=function(){
console.log(this.name);
}
}
function Dog(name){
Animal.call(this,name);
}
var dog=new Dog("Crazy dog");
dog.showName();
输出:Crazy dog复制代码
Animal.call(this) 的意思就是使用 Animal对象代替this对象,那么Dog就能直接调用Animal的全部属性和方法。
2、apply()
语法:apply([thisObj[,argArray]])
定义:应用某一对象的一个方法,用另外一个对象替换当前对象。
说明:
若是 argArray 不是一个有效的数组或者不是 arguments 对象,那么将致使一个 TypeError。
若是没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用做 thisObj, 而且没法被传递任何参数。
call 和 apply的区别
对于 apply、call 两者而言,做用彻底同样,只是接受参数的方式不太同样。
function class1(args1,args2){
this.name=function(){
console.log(args,args);
}
}
function class2(){
var args1="1";
var args2="2";
class1.call(this,args1,args2);
/*或*/
class1.apply(this,[args1,args2]);
}
var c=new class2();
c.name();
输出:1 2复制代码
call
须要把参数按顺序传递进去,而 apply
则是把参数放在数组里。
既然二者功能同样,那该用哪一个呢?
在JavaScript 中,某个函数的参数数量是不固定的,所以要说适用条件的话,当你的参数是明确知道数量时用 call ;而不肯定的时候用 apply,而后把参数 push 进数组传递进去。当参数数量不肯定时,函数内部也能够经过 arguments 这个类数组对象来遍历全部的参数。
3、bindbind
是在EcmaScript5中扩展的方法(IE6,7,8不支持)bind()
方法与 apply 和 call 很类似,也是能够改变函数体内 this
的指向。
MDN的解释是:bind()
方法会建立一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以建立它时传入 bind()
方法的第一个参数做为 this
,传入 bind()
方法的第二个以及之后的参数加上绑定函数运行时自己的参数按照顺序做为原函数的参数来调用原函数。
注意:bind
方法的返回值是函数
var bar=function(){
console.log(this.x);
}
var foo={
x:3
}
bar();
bar.bind(foo)();
/*或*/
var func=bar.bind(foo);
func();
输出:
undefined
3复制代码