我有時發現有道雲筆記其中有段代碼用到了apply方法用於遞歸實現數組的展開。但是我不懂這個函數的用法,所以查了一下,將資料整理以下。 javascript
Javascript的每一個Function對象中有一個apply方法: html
1 |
function.apply([thisObj[,argArray]]) |
還有一個相似功能的call方法: java
1 |
function.call([thisObj[,arg1[, arg2[, [,.argN]]]]]) |
它們各自的定義: 數組
- apply:應用某一對象的一個方法,用另外一個對象替換當前對象。
- call:調用一個對象的一個方法,以另外一個對象替換當前對象。
它們的共同之處: app
- 都「能夠用來代替另外一個對象調用一個方法,將一個函數的對象上下文從初始的上下文改變爲由 thisObj 指定的新對象。」——摘自JScript5.5 .chm
它們的不一樣之處: ssh
- 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])
示例代碼(注:註釋中是call的用法,與上面apply的實現效果相同): 函數
(1)基本用法: this
(2)實現繼承: spa
01 |
function Animal(name){ |
03 |
this.showName = function(){ |
09 |
Animal.apply(this, [name]); |
10 |
//Animal.call(this, name); |
13 |
var cat = new Cat("Black Cat"); |
(3)多重繼承:
03 |
this.showSub = function(a,b) |
11 |
this.showAdd = function(a,b) |
apply的其餘巧妙用法:
看到這裏,我就會以爲既然apply和call的用法差很少,那麼爲何還同時存在這兩種方法呢?徹底能夠丟掉一個呀。後來才發現一篇文章中講到apply由於它所傳參數爲數組這一特色還有許多其餘的妙用。 .net
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的方式巧妙地解決這個問題。
參考資源:
(1)[JavaScript]Call和Apply方法
(2)JS中的call()和apply()方法
(3)Js apply方法詳解
補充資料:
(1)javascript中apply方法和call方法的做用以及prototype.js中的應用
(2)js中apply方法的使用
(3)js中apply方法的使用(2)