2011-09-01 134 views
4

一般認爲,應該將Javascript代碼包裝在一個函數中以防止泄漏到全局範圍,並將每個函數之外所需的任何內容分配給head對象(網頁瀏覽器中的window)。Javascript包裝方法之間的區別

我看到的這兩種主要方法在野外:

方法1:

(function() { 
    // code here 
}).call(this); 

方法2:1

(function() { 
    // code here 
})(); 

方法是來自已編譯的CoffeeScript代碼和方法2似乎是jQuery插件的首選風格:

改進方法2的jQuery:

(function($) { 
    // JQuery Code 
})(jQuery); 

問題:之間有什麼方法1方法2區別? CoffeeScript喜歡關注簡潔,所以我認爲CoffeeScript背後的人一定會選擇方法2而不是方法1

回答

4

他們是非常不同的。

方法1使用call,允許你改變什麼this是函數內部。例如:

(function() { 
    alert(this); // DOMWindow 
}).call(window); 


var myObj = {a: 0}; 
(function() { 
    alert(this); // Object => myObj {a: 0} 
}).call(myObj); 

不過要小心,你仍然可以轉儲的東西在全球範圍內有兩種方法:

(function() { 
    a = 5; // global 
    var p = 10; // private to this function 
})(); 
+0

問題詢問有關呼叫(此),它與呼叫(窗口)不同。請參閱CoffeeScript示例,您將看不到呼叫(窗口) – liammclennan

+0

第一個是將函數內的* this *設置爲與函數外部的* this *相同,可能它是全局對象(通常是*窗口*在瀏覽器中,但腳本可能被編寫爲支持非瀏覽器環境)。 – RobG

0

大多數時候是沒有區別的。方法1顯式設置'this'的值將在立即執行的函數中。

2

方法之一,兩者之間的區別取決於上下文它們在使用。

如在方法中的一個,執行功能與call將使用第一參數作爲「這個」內的 功能。在方法二中,函數中的'this'將引用全局對象,因爲'this'沒有被調用設置(除了在ES 5嚴格模式下,它將被定義)。

有了這些知識,試着想想如果這兩個函數都是要加載到瀏覽器中的JS文件的根目錄中的位置,會發生什麼情況。

在這種情況下,在方法一中傳遞給'call'的'this'將引用窗口對象,它是瀏覽器中的全局對象。方法二將完成同樣的事情,因爲'this'未被調用設置的函數將其這個設置爲全局對象(除了如上所述的ES5嚴格模式外)。

因此,對於這種情況,他們會表現相同。

但是,有些情況並非如此。

var obj = { 
    f: function() { 
    (function() { 
     // 'this' here is 'obj' if called as obj.f() 
    }).call(this); 

    (function() { 
     // 'this' not set by the call, defaults to 'window' (ES5 caveat) 
    })(); 
    } 
}; 

obj.f(); 

方法一更清晰,因爲它顯式地傳遞外部'this'的值,減少了混淆的機會,並增加了靈活性。

如果「這個」無關緊要,方法二更短更容易。

jQuery版本用作總是能夠通過'$'變量訪問jQuery的簡單方法,同時仍允許jQuery之外的代碼具有$意味着別的東西。