2012-08-10 61 views
6

這些結構之間有什麼區別,優點/缺點(如果有的話)?Javascript關閉語法

new function(obj) { 
    console.log(obj); 
}(extObj); 

VS

(function(obj) { 
    console.log(obj); 
})(extObj); 
+0

我可以添加 - 是否存在'(函數ion(obj){..})(extObj);'和'function(obj){..})(extObj);'? – 2012-08-10 08:48:07

+2

@Matt沒有任何。 – Christoph 2012-08-10 08:49:17

回答

4

如果你正在尋找與緊挨着的調用函數中明確處理,那麼就沒有任何兩者之間真正的區別,除了第一個將返回this在函數內部,自動地(在new的作用下),並且默認情況下,如果不指定不同的返回值(常規函數返回undefined)。

其餘的主要區別並不是真的很重要 - 訪問原型鏈將是毫無意義的,返回的this.constructor指向匿名函數將允許您訪問緩存匿名函數以供在以後的時間(比如將它從一個事件監聽器中移除,如果你以某種方式設法將所包含的函數粘貼在......中,那本來就是一種技巧)。

允許人們將你立即調用的函數作爲返回的this對象的構造函數屬性進行緩存可能是一種安全風險......或者它可能非常有用......在非常特定的場景中。

每天發佈代碼的目的 - 沒有真正的區別。

+0

一旦涉及到變量賦值的工作,我就不同意你的最後一句話。 – Christoph 2012-08-10 08:34:39

+0

@Christoph如何?我的意思是,如果在那裏沒有變量來捕捉返回語句,那麼函數內部會發生什麼不會有太大的區別。在命名空間模塊或其他任何你可能做的事情上,可能會有很大的後果。如果你正在內聯全局範圍之外的即時程序代碼,它不會被返回到var以備後用,那麼'new'或'('或'!'都將實現幾乎相同的事情, (儘管沒有)副作用 – Norguard 2012-08-10 08:41:31

+0

我同意你的陳述,雖然我認爲以某種方式存儲返回值是很常見的,所以我只想指出,他們對於他們返回的東西的不同行爲可能有主要影響 – Christoph 2012-08-10 08:48:42

9

第一個返回對您的匿名構造函數(= this)的新構建實例的引用。

第二個返回匿名函數的返回值。由於你的函數沒有返回語句,它會隱式地返回undefined。

嘗試以下方法:(順便說一句,t1.constructor將返回你創建t1原有功能)

var t1 = new function(obj) { console.log(obj); }(extObj); 
var t2 = (function(obj) { console.log(obj); })(extObj); 

typeof t1 => "object" 
typeof t2 => "undefined" 

的差別變得更加清晰,如果添加一個return語句:

var t1 = new function(obj){ return(obj); }("foo"); 
var t2 = (function(obj){ return(obj); })("bar"); 

console.log(t1) => "object" 
console.log(t2) => "bar" 

IMO,這使得(function)()更有用的日常用例 - 你分配回報如果你正在使用立即調用的函數,這個函數的執行值通常是你想要的變量。具有像更復雜的事情(僞碼)特別是當:

var myNameSpace = (function(){ 
    /* do some private stuff here*/ 
    ... 
    /* expose parts of your anonymous function by returning them */ 
    return{ 
     functionX, 
     variable1, 
     variable2 
    } 
}(); 

基本上可以使用任意的一元運算符打開函數聲明到表達,也就是立即調用。所以你也可以這樣寫:

!function(){ /* code */ }(); 
~function(){ /* code */ }(); 
-function(){ /* code */ }(); 
+function(){ /* code */ }(); 

根據你的函數的return語句,這些會給出不同的返回結果。 ! - 否定返回值+|-評估爲數字(適用負號)~bitwise not應用於返回值。

1

另一個區別是第一次調用會創建一個額外的對象。在這裏,我把名字fo表示的對象:

var o = new function f(obj) { 
    console.log(obj); 
}(extObj); 

在第二種情況下,我們仍然創造一個函數對象f,但我們不創建一個o

(function f(obj) { 
    console.log(obj); 
})(extObj); 

的封閉仍然被創建,但是它比實際的JavaScript對象便宜,因爲它沒有攜帶整個原型鏈或其他屬性(如隱藏類參考),

+0

這並不完全正確。你可以在第二種情況下創建一個對象o,但由於沒有返回值,所以'o'被分配了該函數的隱式返回值,該值是未定義的。 – Christoph 2012-08-10 08:06:54

+0

所以,'o'將會是未定義的,並且不會創建對象,對吧? – 2012-08-10 12:17:55

+0

如果你要寫'var o =(function ...',那麼o就存在賦值爲「undefined」的值,這是非常無用的,因爲你無法區別它也返回「undefined」 ,但仍然存在'o',你需要爲此寫'delete window.o' – Christoph 2012-08-10 12:26:29