JavaScript中的call()和apply()都是用于调用当前函数functionObject,并可同时使用指定对象thisObj作为本次执行时functionObject函数内部的this指针引用。它们都输属于
Function对象,所有主流浏览器均支持。
1. call()和apply()的定义
1.1 call()方法
定义:调用一个对象的一个方法,以另一个对象替换当前对象。
语法:functionObject.call( [ thisObj [, arg1 [, arg2 [, args...]]]] )
参数:
| 参数 | 描述 | 
|---|---|
thisObj | 
可选/Object类型,指定执行functionObject函数时,函数内部this指针引用的对象。 | 
arg1 | 
可选/任意类型,调用functionObject函数时传入的第1个参数。 | 
arg2 | 
可选/任意类型,调用functionObject函数时传入的第2个参数。 | 
args | 
可选/任意类型,调用functionObject函数时传入的更多参数,可以有多个。 | 
1.2 apply()方法
定义:应用一个对象的一个方法,用另一个对象替换当前对象。
语法:functionObject.apply( [ thisObj [, argsArray ]] )
参数:
| 参数 | 描述 | 
|---|---|
thisObj | 
可选/Object类型,指定执行functionObject函数时,函数内部this指针引用的对象。 | 
argsArray | 
可选/Array或arguments对象,调用functionObject时传入的参数数组或arguments对象。 | 
1.3 call()和apply()的异同
相同点:
都可以用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象。
不同点:
call():则是直接的参数列表,主要用在js对象各方法互相调用的时候,使当前this实例指针保持一致,或在特殊情况下需要改变this指针。如果没有提供thisObj参数,那么Global对象被用作thisObj。apply():最多只能有两个参数———新this对象和一个数组argsArray。如果给该方法传递多个参数,则把参数都写进这个数组里面,当然,即使只有一个参数,也要写进数组里面。如果 argArray 不是一个有效的数组或者不是arguments对象,那么将导致一个TypeError。如果没有提供argsArray和thisObj任何一个参数,那么Global对象将被用作thisObj,并且无法被传递任何参数。
总结:
call()和apply()都可以用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象。call()函数是将FunctionObject的参数一个个分别传入,如functionObject.call(thisObj,arg1,arg2,arg3);apply()函数是将FunctionObject对象的参数以一个数组或arguments对象的形式整体传入,如functionObject.apply(func1,[arg1,arg2,arg3])。
2. call()和apply()实例
2.1 实例一
  | 
  | 
说明:
例子中用add来替换sub,add.call(sub,3,1) == add(3,1),所以运行结果为:4; 
需要注意的是,这里直接用了函数名sub,而不是sub(),因为在js中的函数其实是对象,函数名是对Function 对象的引用。 
2.1 实例二
  | 
  | 
说明
通过call或apply方法,将原本属于Animal对象的showName()方法交给对象cat来使用了。因此输入结果为"Cat"。
2.3 实例三(实现继承)
  | 
  | 
说明:
Animal.call(this, name) 的意思就是使用 Animal对象代替this对象,那么Cat对象就能够直接调用Animal的方法以及属性了。
2.4 实例四(多重继承)
  | 
  | 
3. apply()的其他妙用
既然apply和call的用法差不多,那么为什么还同时存在呢?
——这是因为apply所传的参数类型(数组)还有其他妙用。
3.1 Math.max可以实现得到数组中最大的一项
因为Math.max参数不支持数组传递,但是它支持列表传递,即Math.max(param1,param2,param3…),所以可以根据apply的特点来解决 var max=Math.max.apply(null,array),这样轻易的可以得到一个数组中最大的一项。(apply会将一个数组转换为一个参数接一个参数的传递给方法)。 
注意:调用的时候第一个参数给了一个null,是因为没有对象去调用这个方法,只需要用这个方法帮助运算,得到返回的结果就行,所以直接传递了一个null过去。
3.2 Array.min 可以实现得到数组中最小的一项
同样和max是一个思想 var min=Math.min.apply(null,array)。 
3.3 Array.prototype.push 可以实现两个数组合并
同样push方法没有提供push一个数组,但是它提供了push(param1,param,…paramN) 所以同样也可以通过apply来转换一下这个数组,即: 
  | 
  | 
也可以这样理解,arr1调用了push方法,参数是通过apply将数组装换为参数列表的集合。 
总结:
当目标函数只需要n个参数列表,而不接收一个数组的形式([param1[,param2[,…[,paramN]]]]),可以通过apply的方式巧妙地解决这个问题。