一直都沒太明白apply()與call()的具體使用原理,今日閑來無事,決定好好研究一番。
JavaScript中的每一個Function對象都有一個apply()方法和一個call()方法,它們的語法分別為:
/*apply()方法*/function.apply(thisObj[, argArray])/*call()方法*/function.call(thisObj[, arg1[, arg2[, [,...argN]]]]);
它們各自的定義:
apply:應用某一對象的一個方法,用另一個對象替換當前對象。例如:B.apply(A, arguments);即A對象應用B對象的方法。
call:調用一個對象的一個方法,以另一個對象替換當前對象。例如:B.call(A, args1,args2);即A對象調用B對象的方法。
它們的共同之處:
都“可以用來代替另一個對象調用一個方法,將一個函數的對象上下文從初始的上下文改變為由thisObj指定的新對象”。
它們的不同之處:
apply:最多只能有兩個參數——新this對象和一個數組argArray。如果給該方法傳遞多個參數,則把參數都寫進這個數組里面,當然,即使只有一個參數,也要寫進數組里。如果argArray不是一個有效的數組或arguments對象,那么將導致一個TypeError。如果沒有提供argArray和thisObj任何一個參數,那么Global對象將被用作thisObj,并且無法被傳遞任何參數。
call:它可以接受多個參數,第一個參數與apply一樣,后面則是一串參數列表。這個方法主要用在js對象各方法相互調用的時候,使當前this實例指針保持一致,或者在特殊情況下需要改變this指針。如果沒有提供thisObj參數,那么 Global 對象被用作thisObj。
實際上,apply和call的功能是一樣的,只是傳入的參數列表形式不同。
示例代碼:
(1)基本用法
functionadd(a,b){returna+b;
}functionsub(a,b){returna-b;
}vara1 = add.apply(sub,[4,2]);//sub調用add的方法vara2 = sub.apply(add,[4,2]);
alert(a1);//6alert(a2);//2
/*call的用法*/
vara1 = add.call(sub,4,2);
(2)實現繼承
functionAnimal(name){this.name =name;this.showName =function(){
alert(this.name);
}
}functionCat(name){
Animal.apply(this,[name]);
}varcat =newCat("咕咕");
cat.showName();/*call的用法*/Animal.call(this,name);
(3)多重繼承
functionClass10(){this.showSub =function(a,b){
alert(a-b);
}
}functionClass11(){this.showAdd =function(a,b){
alert(a+b);
}
}functionClass12(){
Class10.apply(this);
Class11.apply(this);//Class10.call(this);//Class11.call(this);}varc2 =newClass12();
c2.showSub(3,1);//2c2.showAdd(3,1);//4
apply的一些其他巧妙用法
(1)Math.max 可以實現得到數組中最大的一項:
因為Math.max不支持Math.max([param1,param2])也就是數組,但是它支持Math.max(param1,param2...),所以可以根據apply的特點來解決 var max=Math.max.apply(null,array),這樣就輕易的可以得到一個數組中的最大項(apply會將一個數組轉換為一個參數接一個參數的方式傳遞給方法)
這塊在調用的時候第一個參數給了null,這是因為沒有對象去調用這個方法,我只需要用這個方法幫我運算,得到返回的結果就行,所以直接傳遞了一個null過去。
用這種方法也可以實現得到數組中的最小項:Math.min.apply(null,array)
(2)Array.prototype.push可以實現兩個數組的合并
同樣push方法沒有提供push一個數組,但是它提供了push(param1,param2...paramN),同樣也可以用apply來轉換一下這個數組,即:
1.var arr1=new Array("1","2","3");
2.var arr2=new Array("4","5","6");
3.Array.prototype.push.apply(arr1,arr2); ? ?//得到合并后數組的長度,因為push就是返回一個數組的長度
也可以這樣理解,arr1調用了push方法,參數是通過apply將數組轉換為參數列表的集合
通常在什么情況下,可以使用apply類似Math.max等之類的特殊用法:
一般在目標函數只需要n個參數列表,而不接收一個數組的形式,可以通過apply的方式巧妙地解決這個問題。