這些結構之間有什麼區別,優點/缺點(如果有的話)?Javascript關閉語法
new function(obj) {
console.log(obj);
}(extObj);
VS
(function(obj) {
console.log(obj);
})(extObj);
這些結構之間有什麼區別,優點/缺點(如果有的話)?Javascript關閉語法
new function(obj) {
console.log(obj);
}(extObj);
VS
(function(obj) {
console.log(obj);
})(extObj);
如果你正在尋找與緊挨着的調用函數中明確處理,那麼就沒有任何兩者之間真正的區別,除了第一個將返回this
在函數內部,自動地(在new
的作用下),並且默認情況下,如果不指定不同的返回值(常規函數返回undefined
)。
其餘的主要區別並不是真的很重要 - 訪問原型鏈將是毫無意義的,返回的this.constructor
指向匿名函數將允許您訪問緩存匿名函數以供在以後的時間(比如將它從一個事件監聽器中移除,如果你以某種方式設法將所包含的函數粘貼在......中,那本來就是一種技巧)。
允許人們將你立即調用的函數作爲返回的this
對象的構造函數屬性進行緩存可能是一種安全風險......或者它可能非常有用......在非常特定的場景中。
每天發佈代碼的目的 - 沒有真正的區別。
一旦涉及到變量賦值的工作,我就不同意你的最後一句話。 – Christoph 2012-08-10 08:34:39
@Christoph如何?我的意思是,如果在那裏沒有變量來捕捉返回語句,那麼函數內部會發生什麼不會有太大的區別。在命名空間模塊或其他任何你可能做的事情上,可能會有很大的後果。如果你正在內聯全局範圍之外的即時程序代碼,它不會被返回到var以備後用,那麼'new'或'('或'!'都將實現幾乎相同的事情, (儘管沒有)副作用 – Norguard 2012-08-10 08:41:31
我同意你的陳述,雖然我認爲以某種方式存儲返回值是很常見的,所以我只想指出,他們對於他們返回的東西的不同行爲可能有主要影響 – Christoph 2012-08-10 08:48:42
第一個返回對您的匿名構造函數(= 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
應用於返回值。
另一個區別是第一次調用會創建一個額外的對象。在這裏,我把名字f
和o
表示的對象:
var o = new function f(obj) {
console.log(obj);
}(extObj);
在第二種情況下,我們仍然創造一個函數對象f
,但我們不創建一個o
:
(function f(obj) {
console.log(obj);
})(extObj);
的封閉仍然被創建,但是它比實際的JavaScript對象便宜,因爲它沒有攜帶整個原型鏈或其他屬性(如隱藏類參考),
這並不完全正確。你可以在第二種情況下創建一個對象o,但由於沒有返回值,所以'o'被分配了該函數的隱式返回值,該值是未定義的。 – Christoph 2012-08-10 08:06:54
所以,'o'將會是未定義的,並且不會創建對象,對吧? – 2012-08-10 12:17:55
如果你要寫'var o =(function ...',那麼o就存在賦值爲「undefined」的值,這是非常無用的,因爲你無法區別它也返回「undefined」 ,但仍然存在'o',你需要爲此寫'delete window.o' – Christoph 2012-08-10 12:26:29
我可以添加 - 是否存在'(函數ion(obj){..})(extObj);'和'function(obj){..})(extObj);'? – 2012-08-10 08:48:07
@Matt沒有任何。 – Christoph 2012-08-10 08:49:17