Javascript call與apply記錄

【註】:記錄自己對javascript中call與apply的見解

 

總會有些東西會被人拿出來重復的寫來寫去,為何?

 

隻是因為自己感覺不夠瞭解,所謂好記性不如爛筆頭,並且在寫的同時也會或多或少的收獲到一些額外的知識,這才是重點(但是必須用心去寫)

 

 

 

call 概念

 

【概念】:調用一個對象的一個方法,以另一個對象替換當前對象 或者(劫持另外一個對象的方法,繼承另外一個對象的屬性)

 

【函數】:Function.call(obj,[param1[,param2[,…[,paramN]]]])

 

【參數】:obj:“可選項。這個對對象將替代Function類裡面的this。”,param1, param2,  , paramN:“可選項。將被傳遞方法參數序列。”

 

【說明】:call 方法可以用來代替另一個對象調用一個方法。call 方法可將一個函數的對象上下文從初始的上下文改變為由 obj 指定的新對象。如果沒有提供 obj參數,那麼 Global 對象被用作 obj

 

例子

 

復制代碼

var a = 1, b = 2;       //申明全局變量a,b

var o = { a: 3, b: 4}    //申明對象o

 

//打印出當前對象

function funCall() {    

    console.log(this);

}

 

funCall();          //直接調用–>this=window

funCall.call();     //調用funCall方法的call方法–>this=window

funCall.call(o);    //以o作為參數調用funCall方法的call方法–>this=o

復制代碼

 

 

 

 

apply概念

 

【概念】:和call的意思一樣,隻不過是參數列表不一樣

 

【函數】:Function.apply(obj,args)

 

【參數】:obj:“可選項。這個對對象將替代Function類裡面的this。”,args:“可選項。這個是數組,它將作為參數傳給Function(args–>arguments)”

 

【說明】:和call的意思一樣,隻不過是參數列表不一樣

 

例子

 

復制代碼

var a = 1, b = 2;       //申明全局變量a,b

var o = { a: 3, b: 4}    //申明對象o

 

//打印出當前對象

function funApply() {    

    console.log(this);

}

 

funApply();         //直接調用–>this=window

funApply.apply();   //調用funApply方法的apply方法–>this=window

funApply.apply(o);  //以o作為參數調用funApply方法的apply方法–>this=o

復制代碼

 

 

 

 

call與apply區別,以及什麼時候用call、什麼時候用apply

 

【this】首先說下我心中的this:哪個上下文對象調用對應的Function,Funtion中的this就是該上下文對象(Funtion中調用另外一個Funtion,this則會指向window,閉包瞭~~~~)

 

通過上述概念的介紹,可以看出call與apply的唯一區別在於參數列表(上述例子中隻調用瞭call與apply的一個參數的重載方法)

 

復制代碼

var a = 1, b = 2, c = 5;        //申明全局變量a,b

var o = { a: 3, b: 4, e: 6}     //申明對象o

 

//打印出當前對象

function funCallorApply() {

    console.log(a);

    console.log(b);

    console.log(c);

    console.log(this);

}

復制代碼

 

 

1,call的多參數調用

 

call多參數調用還蠻有趣的(至少我是這麼理解的),它和jQuery的extend有點相似

 

funCallorApply.call(o, a, b, c);

//結果:

//1

//2

//5

//Object {a: 3, b: 4, e: 6}

從上述的結果可以知道:call中的第一個參數對象會被替換成觸發方法的this,後續都會被當作參數進行傳遞

 

 

 

2,apply的多參數調用

 

apply則不像call可以代入多個參數,apply隻有2個參數,第二個參數需要以數組的形式存在,所以參數是以對象數組的方式進行傳遞。

 

funCallorApply.apply(o, [a, b, c]);

//結果

//1

//2

//5

//Object {a: 3, b: 4, e: 6}

從上述結果可以知道:apply和call一樣第一個參數對象會被替換被替換成觸發方法的this,不通的是參數傳遞的方式

 

 

 

3,什麼時候用call,什麼時候用apply

 

其實我一般用的是apply,它可以將參數以對象數組的方式傳遞(因為我喜歡這種方式傳遞參數,因為這樣可以在方法中設置默認值,然後通過extend繼承去重新默認值)。

 

理論說來要看你方法是怎麼構造的瞭

 

復制代碼

//方法是這樣就可以考慮使用call

function funCallorApply(a, b, c) {

    this.a = a;

    this.b = b;

    this.c = c;

    //具體的實現

}

funCallorApply.call(o, a, b, c);

 

//方法是這樣可以考慮使用apply

function funCallorApply(obj) {

    this.a = obj.a;

    this.b = obj.b;

    this.c = obj.c;

    //具體的實現

}

funCallorApply.apply(o, [a, b, c]);

復制代碼

一般為瞭方法的擴展,將參數以數組的形式進行傳遞是個不錯的方式。如果需要改參數就不需要去動其它調用的地方瞭。

 

 

 

 

 

apply的額外補充

 

在紫雲飛的文章中發現瞭一點apply的額外用處(學淺,隻能把第一個運用到實際開發中尷尬)

 

 

 

細心的人可能已經察覺到,在我調用apply方法的時候,第一個參數是對象(this),第二個參數是一個數組集合。

 

在調用funCallorApply.apply(o, [a, b, c])的時候,第二參數是一個數組,但是為什麼我仍然可以將數組解析為一個一個的參數?

 

這個就是apply的一個巧妙的用處,可以將一個數組默認的轉換為一個參數列表([param1,param2,param3] 轉換為 param1,param2,param3) ,這個如果讓我們用程序來實現將數組的每一個項,來裝換為參數的列表,可能都得費一會功夫,借助apply的這點特性,所以就有瞭以下高效率的方法:

 

 

 

1,獲取數組中的最大值通過Math.max

 

//JavaScript中沒有返回一個數組中最大值的函數.但是,有一個函數Math.max可以返回任意多個數值類型的參數中的最大值.再配合apply,我們可以實現我們的目的

Math.max.apply(null, [3, 8, 10, -1, 5]);    //結果–>10

Math.min最小值也一樣應用

 

 

 

2,數組合並

 

//同樣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);

Array.prototype.push.apply會返回合並後數組的length,上面結果是6,合並之後arr1就變成瞭["1", "2", "3", "4", "5", "6"]

 

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *