一、定义
- apply:应用某一对象的一个方法,用另一个对象替换当前对象。
- call:调用一个对象的一个方法,以另一个对象替换当前对象。
二、apply
//apply
function Person(name,age){
this.name=name;
this.age=age; this.getName=function(){
console.log("姓名:"+this.name);
} this.getAge=function(){
console.log("年龄:"+this.age);
}
} function Student(name,age,grade){
Person.apply(this,arguments);
this.grade=grade; this.getGrade=function(){
console.log("年级:"+this.grade);
}
} console.log("apply:")
var student=new Student('gkl',20,6);
student.getName();
student.getAge();
student.getGrade();
测试结果:
aaarticlea/png;base64,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" alt="" />
分析:
Person.apply(this,arguments);
this:在创建对象在这个时候代表的是student
arguments:是一个数组,也就是[“gkl”,20,6];
student去执行Person这个类里面的内容,在Person这个类里面存在this.name等之类的语句,这样就将属性创建到了student对象里面
三、call
call方法只是参数格式不一样
//call
function Person1(age,name){
this.name=name;
this.age=age; this.getName=function(){
console.log("姓名:"+this.name);
} this.getAge=function(){
console.log("年龄:"+this.age);
}
} function Student1(name,age,grade){
Person.call(this,age,name);
this.grade=grade; this.getGrade=function(){
console.log("年级:"+this.grade);
}
} console.log("call:");
var student1=new Student1('gkl',20,6);
student1.getName();
student1.getAge();
student1.getGrade();
效果和apply一致
四、巧妙用法
a) Math.max 可以实现得到数组中最大的一项:
因为Math.max 参数里面不支持Math.max([param1,param2]) 也就是数组,但是它支持Math.max(param1,param2,param3…),所以可以根据apply的特点来解决 var max=Math.max.apply(null,array),这样轻易的可以得到一个数组中最大的一项(apply会将一个数组转换为一个参数接一个参数的传递给方法)。这块在调用的时候第一个参数给了一个null,这个是因为没有对象去调用这个方法,只需要用这个方法帮助运算,得到返回的结果就行,所以直接传递了一个null过去
b) Math.min 可以实现得到数组中最小的一项:
同样和 max是一个思想 var min=Math.min.apply(null,array)。
c) Array.prototype.push 可以实现两个数组合并:
同样push方法没有提供push一个数组,但是它提供了push(param1,param,…paramN) 所以同样也可以通过apply来转换一下这个数组,即:
var arr1=new Array("1","2","3");
var arr2=new Array("4","5","6");
Array.prototype.push.apply(arr1,arr2);
也可以这样理解,arr1调用了push方法,参数是通过apply将数组装换为参数列表的集合。
d) 小结:通常在什么情况下,可以使用apply类似Math.min等之类的特殊用法:
一般在目标函数只需要n个参数列表,而不接收一个数组的形式([param1[,param2[,…[,paramN]]]]),可以通过apply的方式巧妙地解决这个问题。
五、异同
共同之处:
- 都“可以用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。”——摘自JScript5.5 .chm
不同之处:
- apply:最多只能有两个参数——新this对象和一个数组 argArray。如果给该方法传递多个参数,则把参数都写进这个数组里面,当然,即使只有一个参数,也要写进数组里面。如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。
- call:则是直接的参数列表,主要用在js对象各方法互相调用的时候,使当前this实例指针保持一致,或在特殊情况下需要改变this指针。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
- 更简单地说,apply和call功能一样,只是传入的参数列表形式不同:如 func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3])
参考资料:
(1)http://my.oschina.net/warmcafe/blog/74973
补充资料: