JavaScript中call()與apply()有什麼區別?

今天讀《JavaScript權威指南》時發現其中有段代碼用到了apply方法用於遞歸實現數組的展開。但是我不懂這個函數的用法,所以查了一下,將資料整理以下。 javascript

Javascript的每一個Function對象中有一個apply方法: html

function.apply([thisObj[,argArray]])

還有一個相似功能的call方法: java

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

function add(a,b)
{
    alert(a+b);
}
function sub(a,b)
{
    alert(a-b);
}

add.apply(sub,[3,1]);
//add.call(sub,3,1);

(2)實現繼承: .net

function Animal(name){    
    this.name = name;    
    this.showName = function(){    
        alert(this.name);    
    }    
}    
   
function Cat(name){  
    Animal.apply(this, [name]);
    //Animal.call(this, name);  
}    
   
var cat = new Cat("Black Cat");   
cat.showName();
(3)多重繼承:
function Class10()
{
    this.showSub = function(a,b)
    {
        alert(a-b);
    }
}

function Class11()
{
    this.showAdd = function(a,b)
    {
        alert(a+b);
    }
}

function Class2()
{
    Class10.apply(this);
    Class11.apply(this);
    //Class10.call(this);
    //Class11.call(this);
}

var c2=new Class2();
c2.showSub(3,1);
c2.showAdd(3,1);
apply的其餘巧妙用法:

看到這裏,我就會以爲既然apply和call的用法差很少,那麼爲何還同時存在這兩種方法呢?徹底能夠丟掉一個呀。後來才發現一篇文章中講到apply由於它所傳參數爲數組這一特色還有許多其餘的妙用。 prototype

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)

相關文章
相關標籤/搜索