首頁  >  問答  >  主體

javascript - 關於apply()與call()的問題

function sum(num1,num2) {
    return num1 + num2;
}
function callSum1(num1,num2) {
    return sum.apply(this,arguments);
}
function callSum2(num1,num2) {
    return sum.apply(this,[num1,num2]);
}

alert(callSum1(10,10));
alert(callSum2(10,10));

//call()例子就省略了

問:
1.sum.apply(this,arguments)說的是物件sum呼叫apply方法,this指的是callSum()與sum()都是同一個作用域運行,arguments指的就是”sum1,sum2”?
2.apply()與call()的在專案中應用價值是什麼?

滿天的星座滿天的星座2663 天前1134

全部回覆(5)我來回復

  • 淡淡烟草味

    淡淡烟草味2017-07-05 11:03:57

    樓上寫的真複雜:)

    聽我講,題主疑惑的地方
    1:

    function callSum1(num1,num2) {
        return sum.apply(this,arguments);    // 这里的arguments和下面的[num1,num2]是同一个意思
    }
    function callSum2(num1,num2) {
        return sum.apply(this,[num1,num2]);
    }

    arguments 是一個類似陣列的物件, 對應於傳遞給函數的參數。 arguments物件是所有函數中可用的局部變數。你可以使用arguments物件在函數中引用函數的參數。

    PS:this的指向在函數定義的時候是確定不了的,只有函數執行的時候才能確定this到底指向誰,實際上this的最終指向的是那個調用它的對象

    2、call和apply應用價值(存在的意義):

    作用都是為了改變函數運行時的上下文而存在。 即改變函數體內部this的指向
    "說白點,a有xx方法,b沒有。b可以問a借!"(這tm不就是繼承嘛~)

    call和apply不同點:

    接受參數方式不一樣。

    如下:
    call接受的是連續參數,apply接受的是陣列參數。
    A.call(this, a,b,c,d)
    A.apply(this, [a,b,c,d])

    一個傳送門:http://www.jianshu.com/p/a7b1...

    回覆
    0
  • typecho

    typecho2017-07-05 11:03:57

    1. arguments是function內建屬性之一,表示函數數組對象,即 callSum1裡的arguments 指涉 num1和num2
      https://developer.mozilla.org...

    2. apply 跟call的價值在於,能夠使得指定函數裡面的this指向特定的對像上,舉個例子,我們用document.querySelectorAll()獲取的dom其實是一個類數組對象,非數組,如果想要用陣列的方法時,可以是這樣

    var doms = document.querySelectorAll('p');
    [].forEach.call(doms, function(e){
        //遍历元素
    });

    而apply 跟call主要區別在於參數格式,這個建議題主翻翻MDN。

    回覆
    0
  • 巴扎黑

    巴扎黑2017-07-05 11:03:57

    1.sum.apply(this,arguments)說的是物件sum呼叫apply方法,this指的是callSum()與sum()都是同一個作用域運行,arguments指的就是」sum1,sum2」?

    2.apply()與call()的在專案中應用價值是什麼?

    針對 1 執行結果兩個都回傳 20 20

    sum.apply(this,arguments) 指的是用apply來呼叫sum 指定sum執行的時候的this為現在的這個this 後面的arguments是參數列表是一個類別數組對象,你可以簡單地當成數組對待。

    sum.apply(this,[num1, num2]) 與上方類似。

    關於arguments,發一張截圖你可能就會有感性的認識了


    以下是針對第二點的回答

    欽點this

    比較好理解 就是改變 this 指向在 ajax 請求的 success 回呼的時候

    例如在vue開發的時候 如果沒有箭頭函數 得要用 var that = this 這樣暫存 this。 如果可以欽點this就沒這些問題

    舉個栗子

    function sayName(){
        console.log(this.name); 
    }
    
    var xiao_ming = {
        name: '小明妹妹'
    }
    
    // 钦点 this 
    sayName.call(xiao_ming); 

    把類別數組物件轉換成真丶數組

    arguments 透過類別數組物件的形式 保存著函數的參數列表 。

    function sumAll(){
        var argu = Array.prototype.slice.call(arguments); 
        
        // 从 0 开始积、每次 sum + cur 作为下次的 sum 
        return argu.reduce((sum, cur) => sum + cur, 0); 
    }

    其實從這裡可以窺見:執行 slice 只需要物件具備 length 正確的下標 就可以正常執行 並回傳結果。

    因為數組的許多方法都可以用在類別數組物件上,因此類別數組物件很多時候確實可以被認為就是數組。

    // 声明一个类数组对象 
    var a = {
        0: 'hello',
        1: 'seg',
        2: 'ment',
        3: 'fault',
        length: 4
    }
    
    // forEach 
    Array.prototype.forEach.call(a, elem => console.log(elem)); 
    // => 遍历打印
    
    // reduce 
    var helloSF = Array.prototype.reduce.call(a, (acc, cur) => acc + cur + ' ', ''); 
    console.log(helloSF); 
    // => 
    // "hello seg ment fault "
    


    還可以做的更像陣列

    var a = {
        0: 'hello',
        1: 'seg',
        2: 'ment',
        3: 'fault',
        length: 4
    }
    
    a.__proto__ = Array.prototype; 
    a.forEach(e => console.log(e)); 
    Array.prototype.reduce.call(a, (acc, cur) => acc + cur + ' ', ''); 

    Object Really Like Array

    實作偏函數 Partial Function

    跟數學上的偏函數類似,例如:

    函數f(x, y) = x + y
    如果令y = k 那麼可以得到偏函數f(x, k) = x + k
    ( 或者這樣可能更好理解: f (x, 4) = x + 4 )

    一般都是用 bind 來實現偏函數的。 不過 apply 和 call 和 bind 應該要集中的講講。

    function logger(type){
        return console.log.bind(console, type); 
    }

    用 apply 實現上述 logger 就是:

    function logger2(type){
        return function(){
            var argu = Array.prototype.slice.call(arguments);  
            argu.unshift(type); 
            console.log.apply(console, argu); 
        }
    }

    高階函數與柯里化

    高階函數一般指的是返回值是函數或其參數是函數的函數。

    setTimeout 是個很好的例子 它接受一個參數(一般是函數) 然後在一定時延後執行它。
    不過傳進去之後一般 this 就指向了 全域物件 window 如果想要欽點 this 就得用 call apply 和 bind

    上面的 logger2 就做到了這點 回傳了一個函數出去


    關於柯里化 先看函數 add

    function add(x, y){
        return a + b; 
    }
    
    add(1, 2); 
    // => 
    // 3 

    如果參數能一個一個的傳 傳到第二個的時候就得到結果:

    var add1 = add(1); 
    add1(2); 
    // => 3 
    
    add(3)(4); 
    // => 7

    第一次執行回傳了一個函數,如果把add 看成是數學意義上的函數那就是f(x, y) = x + y 我們執行了一次add(1) 得到add1 其實就是令x = 1 了,於是得到偏函數

    f(1, y) = 1 + y

    第二次再執行 y 會得到實際值 算式就可以算出結果出來。

    這其實是一步步消元的過程。


    有什麼用的?

    我在函數式程式設計方面也才初學,還沒領會到精髓,唯一對柯里化體會的用處是惰性求值
    剛剛的運算在參數給齊之前不會運行等到參數夠了就會算出結果。


    大半夜不睡覺刷sf 只能想到這些了。 。 。 。

    回覆
    0
  • 过去多啦不再A梦

    过去多啦不再A梦2017-07-05 11:03:57

    手動設定this作用域。

    回覆
    0
  • 迷茫

    迷茫2017-07-05 11:03:57

    百度一下你就知道。

    回覆
    0
  • 取消回覆