js 關於apply和call的理解使用

  關於call和apply,之前也思考良久,不少時候都覺得記住了,可是,我太難了。今天我特意寫下筆記,但願能夠徹底掌握這個東西,也但願能夠幫助到任何想對學習這個東西的同窗。數組

一.apply函數定義與理解,先從apply函數出發app

  在MDN上,apply的定義是:ide

    「apply()方法調用一個具有給定this值的函,以及做爲一個數組(或相似數組對象)提供的參數。」函數

  個人理解是:apply的前面有個含有this的對象,設爲A,apply()的參數裏,也含有一個含有this的對象設爲B。則A.apply(B),表示A代碼執行調用了B,B代碼照常執行,執行後的結果做爲apply的參數,而後apply把這個結果所指表明示的this替換掉A自己的this,接着執行A代碼。學習

  好比:ui

 1     var aa = {
 2         _name:111,
 3         _age:222,
 4         _f:function(){
 5             console.log(this)
 6             console.log(this._name)
 7         }
 8     }
 9     var cc = {
10         _name:0,
11         _age:0,
12         _f:function(){
13             console.log(this)
14             console.log(this._name)
15         }
16     }
17     cc._f.apply(aa)//此時aa表示的this就是aa自己
18     cc._f.apply(aa._f)//此時aa._f表示的this就是aa._f自己
19     
20     /**
21      * 此時aa._f()表示的this,就是執行後的結果自己。aa._f()執行後,沒有返回值,因此應該是undefined,而undefined做爲call和apply的參數時,call和apply前面的方法 cc._f 的this會替換成全局對象window。
22      * 參考MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply 的參數說明
23      */
24     cc._f.apply(aa._f())

執行結果:this

  1.參數爲aaspa

  

  這兩行的打印的都是來自 cc._f 方法內的那兩句console 。aa的時候算是初始化,裏面的 aa._f 方法沒有執行。prototype

  2.參數爲aa.fcode

  

  這兩行的打印的都是來自 cc._f 方法內的那兩句console 。aa.f 的時候應該也算是初始化,或者是整個函數當參數傳可是不執行這個參數,即 aa._f 方法沒有執行。

  3.參數爲aa.f()

   

  這四行的打印,前面兩行來自 aa._f() 方法執行打印的;後面兩行是來自cc._f()方法打印的。

  後兩行解析:aa._f()執行後,沒有返回值,因此是undefined,在apply執行解析後,cc._f()的this變成的window,因此打印了window。window裏面沒有_name這個屬性,因此undefined。

 

 

二.apply與call的區分

  1.apply()

    A.apply(B, [1,2,3]) 後面的參數是arguments對象或相似數組的對象,它會被自動解析爲A的參數;

    對於A.apply(B) / A.call(B) , 簡單講,B先執行,執行後根據結果去執行A。這個時候,用A去執行B的內容代碼,而後再執行本身的代碼。

  好比:

    var f1 = function(a,b){
        console.log(a+b)
    }
    var f2 = function(a,b,c){
        console.log(a,b,c)
    }
    f2.apply(f1,[1,2])//1 2 undefined

 

  先執行f1,f1執行後(f1是f1,不是f1()執行方法,因此console.log(a+b)這行代碼並無執行,至關於,初始化了代碼f1),因爲沒有返回值,因此結果是undefined,f2執行的時候this指向window;參數中的 」 [1,2] 「,解析後變成 f2 的參數 「 1,2,undefined 」,執行f2方法後,打印出1,2,undefined三個值

  2.call()

    A.call(B, 1,2,3) 後面的參數都是獨立的參數對象,它們會被自動解析爲A的參數;

  好比: 

    var f1 = function(a,b){
        console.log(a+b)
    }
    var f2 = function(a,b,c){
        console.log(a,b,c)
    }
    f2.call(f1,[1,2])//[1,2] undefined undefined
    f2.call(f1,1,2)//1 2 undefined

 

  參數中的 」 [1,2] 「,由於傳入了一個數組,至關於只傳入了第一個參數,b和c參數沒有傳。解析後變成 f2 的參數 「 [1,2],undefined ,undefined 」,執行f2方法後,打印出 [1,2],undefined ,undefined 三個值。

三.apply與call帶來的便利

  1. push();

  push參數是相似(a,b,c,d,e)如此傳輸的,若是在一個數組的基礎上進行傳輸另外一個數組的內容,能夠以下:

    //apply用法
    var arr = new Array(1,2,3)
    var arr1 = new Array(11,21,31)
    Array.prototype.push.apply(arr,arr1)
    console.log(arr)//[1, 2, 3, 11, 21, 31]
    
    //call用法
    var arr = new Array(1,2,3)
    var arr1 = new Array(11,21,31)
    Array.prototype.push.call(arr,arr1[0],arr1[1],arr1[2])
    console.log(arr)//[1, 2, 3, 11, 21, 31]

 

  2. 數組利用Math求最大和最小值

  apply和call的第一個參數,若是是null或者undefined,則apply或call前面的函數會把this指向window

    //apply的用法
    var _maxNum = Math.max.apply(null,[1,3,2,4,5])
    console.log(_maxNum)//5
    var _minNum = Math.min.apply(null,[1,3,2,4,5])
    console.log(_minNum)//1
    
    //call的用法
    var _maxNum = Math.max.call(null,1,3,2,4,5)
    console.log(_maxNum)//5
    var _minNum = Math.min.call(null,1,3,2,4,5)
    console.log(_minNum)//1

 

四.總結

  簡而言之,apply和call函數的第一個參數都是用來替換this指向的對象;apply的第二個參數使用arguments或者相似數組的參數進行傳參,call的第二個或以上的參數,使用獨立單位,一個一個進行傳參;執行順序是apply或call的第一個參數先執行獲得結果,而後執行apply或call前面的函數,執行的時候用已經執行的結果所指代的this去執行。apply和call的使用除了參數上的使用方式不一樣外,功能是如出一轍的。

  以上內容純屬我的理解,有誤勿噴請指出!謝謝!

相關文章
相關標籤/搜索