2017-08-16 141 views
1
// Replace the method named m of the object o with a version that logs 
// messages before and after invoking the original method. 
function trace(o, m) { 

    // Remember original method in the closure 
    var original = o[m]; 

    // Define the new method 
    o[m] = function() { 

    // Log message 
    console.log(new Date(), "Entering:", m); 

    // Invoke original 
    var result = original.apply(this, arguments); 

    // Log message 
    console.log(new Date(), "Exiting:", m); 

    return result; 
    }; 
} 

您好!上面給出的代碼示例來自我的編碼書。它嘗試使用JavaScript中的apply函數來說明一種名爲「猴子補丁」的練習。我真搞不清楚該行的性質原函數被調用:JS中的執行上下文感到困惑

var result = original.apply(this, arguments); // Invoke original. 

據我瞭解,原來的函數調用也無apply()幫助下寫的,因爲thisarg是this,也就是說執行上下文保持不變:original對象。

第二個困惑點是地獄arguments參數apply()來自哪裏?是的,我知道它是在每個函數調用中生成的一個對象,用於訪問函數參數 - 但此行位於不帶任何參數的匿名函數內。我沒有任何線索,並且很感激任何暗示。

預先感謝您!

+0

@dayuloli那個本地執行環境會是什麼?爲了再次引用我的書,「函數使用範圍鏈在執行定義時生效」,這並不意味着執行環境是匿名函數嗎? –

+0

如果執行上下文是anynomous函數的執行上下文,那麼這是否意味着'arguments'對象是空的(因爲該函數沒有任何參數)?那會是什麼意思?我不想使用原始函數會收到的參數嗎? –

+0

「* thisarg是'this',這就是說執行上下文保持不變:'original' object *」 - 否'original'是應該調用的函數(方法)引用,它不是上下文。而且你不知道'this'上下文是否是'o'(方法被覆蓋的對象) - 它可以是任何東西。因此,我們使用'this'。 – Bergi

回答

2

您的第一個問題:爲什麼需要apply

如果直接在匿名函數調用originalthisoriginal是一定要參考globalundefined在嚴格模式下)。另一方面,匿名函數聲明爲o的一種方法,所以如果您調用o.m(),this內部的匿名函數應該參考o。因爲它保留了語義,所以需要傳遞ooriginal

除了綁定this,apply也可以將參數數組轉換爲單個參數。

function toBeCalled(x,y){ 
    console.log('x is: '+x+" y is:"+y) 
} 

function x(){ 
    toBeCalled(arguments) 
    toBeCalled.apply(this,arguments) 
} 

x('aa','bb','vv') 

//x is: [object Arguments] y is:undefined 
//x is: aa y is:bb 

看到區別?

第二個問題:arguments從哪裏來?

在JavaScript中,arguments是一個函數範圍內的內置變量。 arguments的值只能在調用函數時確定爲,它根本不是固定的。

​​

arguments被分配一個值時被調用x,它是動態的。