apply 和 call 函数
1、定义
我们先看一下这两个函数在Javascript中的API,
void apply([thisObj[,argArray]])
调用一个对象的方法,把当前对象的所有方法属性赋予参数1所指向的对象(如有重名属性或方法直接覆盖。),并且以参数2作为多个参数输入。
thisObj的缺省值是全局对象window
void call([thisObj[,arg1[, arg2[,[,argN]]]]])
call与apply区别在于apply的参数2的数组分为多个输入参数了。
试着理解以下代码的执行结果,深入理解定义。
var person_no1 = { name : ‘Jiminy‘, age : 30, phone : 123, fun : function(){ alert(this.name); } } var person_no2 = { name : ‘John‘, age : 25, phone : 123 } person_no1.fun.call(this);//undefined person_no1.fun.call(person_no1);//Jiminy person_no1.fun.call(person_no2);//John
2、应用
-回调函数
我们在封装一些控件的时候,通常需要一些方法在某些操作之后执行,可以用call或者apply来回调另一个方法。
1 function A(name){ 2 this.name = name; 3 this.showName = function(a){ 4 alert(this.name); 5 alert(a); 6 } 7 } 8 9 function B(name){ 10 console.warn(this); 11 this.name = ‘CCCCC‘; 12 this.alertName = function(){ 13 alert(this.name); 14 } 15 this.showName = function(){ 16 alert(‘TTTTT‘); 17 } 18 var a = new A(‘QQQ‘); 19 //call back 20 a.showName.call(this, ‘x‘); 21 // equal => a.showName.apply(this, [‘x‘]); 22 } 23 B("I‘m B"); 24 //CCCCC 25 //x
代码示例中:
把a.showName这个对象替换给当前对象window,并直接调用匿名函数,alert(window.name) //CCCCC
function A, B 都是 window 对象的函数。
-继承
1 function A(name){ 2 this.name = name; 3 this.showName = function(){ 4 alert(this.name); 5 } 6 } 7 8 function B(name){ 9 this.name = ‘CCCCC‘; 10 this.alertName = function(){ 11 alert(this.name); 12 } 13 this.showName = function(){ 14 alert(‘TTTTT‘); 15 } 16 //执行这条语句之后 17 //函数B就变成了function B(){ 18 // this.name = name; 19 // this.showName = function(){ 20 // alert(this.name); 21 // } 22 // this.alertName = function(){ 23 // alert(this.name); 24 // } 25 //} 26 A.call(this, name); 27 // equal => A.apply(this, [name]); 28 } 29 30 var a = new A("I‘m A"); 31 a.showName(); //I‘m A 32 var b = new B("I‘m B"); 33 b.showName(); //I‘m B 34 b.alertName(); //I‘m B
代码示例中:
B通过A.call(this, name)继承了A的所有属性和方法,并且覆盖了相同的属性和方法!
-多继承
和单继承类似,大家可以尝试着写一下。
-方法参数转数组
我们经常在一些开源的框架里看到Array.prototype.slice.call(arguments)这样的代码,arguments就是方法内部的一个默认属性,是对象类型,包含参数列表
如{
0 : param1,
1 : param2,
....
length : N
}
这样通过调用Array.prototype.slice.call()方法可以把这个对象赋予array.slice方法,由于js调用数组和对象时候array[index]和object[index]结果是一样的,所以输入包含length属性的对象也可以使用这个方法。
function test(a, b, c){ alert(Array.prototype.slice.call(arguments)); } Array.prototype.slice = function(start,end){ var result = new Array(); start = start || 0; end = end || this.length; for(var i = start; i < end; i++){ result.push(this[i]); } return result; } test(‘x‘, ‘y‘, ‘z‘);//对象数组 arguments 用法 alert(Array.prototype.slice.call([‘x‘, ‘y‘, ‘z‘]));//源生数组 alert(Array.prototype.slice.call(‘xyz‘));//字符串数组 alert(Array.prototype.slice.call({0:‘x‘,1:‘y‘,2:‘z‘,length:3}));//对象数组 //x,y,z //x,y,z //x,y,z //x,y,z
3、总结
本文简单介绍了几种apply和call的应用,是本人的经验和参考其他资料所得,在实际开发中,还有很多技巧,需要灵活应用,希望大家能通过本文彻底理解函数的定义,融汇贯通,在结构化代码的同时巧妙地
使用这些方法使得代码优美简洁。
4、参考资料
http://uule.iteye.com/blog/1158829