2012-03-20 28 views
17

答案在UPDATE 2/ANSWER下面嵌入死鬥:自執行的匿名航班嗎功能的「新功能」

感謝約瑟夫幫助我找到答案(雖然我不喜歡它=) 。

原來的問題

雖然在JavaScript中使用Namepsaces時做的最佳做法的一些研究,我碰到這個定義中的「模型模式」的:http://yuiblog.com/blog/2007/06/12/module-pattern/

自從我在YUI2多年前看到它以來,我一直在使用這種模式,本文給出了這個概念的一個很好的概述。但是它沒有涉及的是爲什麼使用「自動執行匿名函數」來代替「新函數」。評論中提到了這個問題,但作者沒有很好地描述。由於這篇文章是4歲以上(我沒有在網上找到答案),我想我會把它帶到這裏。

它已經在關閉,所以? (見:Why is this function wrapped in parentheses, followed by parentheses?其中也不回答我的問題=)。

假設下面的設置代碼..

var MyNamespace = window.MyNamespace || {}; 

這些這是優選的,爲什麼呢?

MyNamespace.UsingNew = new function() { 
    var fnPrivate = function() { 
     return "secrets1"; 
    }; 

    this.property = "value1"; 
    this.method = function() { 
     return "property = " + this.property + ' ' + fnPrivate(); 
    } 
}; 

MyNamespace.UsingSelfEx = (function() { //# <- Added "pre-parens" suggested by chuckj 
    var fnPrivate = function() { 
     return "secrets2"; 
    }; 
    var fnReturn = {}; 

    fnReturn.property = "value2"; 
    fnReturn.method = function() { 
     return "property = " + this.property + ' ' + fnPrivate(); 
    } 

    return fnReturn; 
})(); 

UPDATE:

看來,像jQuery,所有時尚的年輕人使用的是 「自執行的匿名函數」(SEAF)!但我不明白這一點,因爲我發現在定義公開函數時使用.UsingNew方法會更清晰(而不是在需要單獨維護的返回值中,或者被迫使用內聯對象符號)。

爲不需要「即=這種」不爲我舉行的水有很多原因的說法:

  • 爲了避免「無功即=這個」你最終要麼做一個「 var obj「加上一個return語句(必須保留公有的單獨定義)或被迫爲公共屬性/方法使用內聯對象表示法(返回{1,2,3})。
  • 您可以在類/名稱空間的頂部始終創建一個「var that = this」的私有變量,並始終使用「that」。

現在......我想我的開發風格可能會使得.UsingNew模式更容易管理。我的「私人」功能本質上幾乎總是「靜態」的,所以我需要在上下文中傳遞(取代「this」)。我也養成了使用「縮寫」命名空間的習慣,所以當我確實需要訪問「this」時,我只需通過「縮寫」命名空間而不是通過它的完整路徑來引用完整對象。例如: -

var PrivateFunct = function() { 
    var rThis = Cn._.val; //# The abbreviated form of Cn.Renderer.Form.Validation 
    //... 
}; 

,或者如果它是一個專用靜態函數...

var PrivateStaticFunct = function(oContext) { 
    //... 
}; 

其他然後上面給出的原因,我個人覺得在.UsingNew方法多源更具可讀性。我有一個相當廣泛的代碼庫,它使用了.UsingNew模式:http://code.google.com/p/cn-namespace/source/browse/Cn.Web/js/Cn/Validation functionality可能是最簡單的一個快速讀取通道。我也使用一些SEAF函數(請參閱ErrorMessages.js.aspx),但只有在它們有意義時才適用。

我無法想象必須維護單獨的回報以公開底部的公共接口!呸!

現在,請不要誤會我的意思,有很多地方SEAF對於強制關閉非常有用,但我個人認爲它在對象內過度使用。

更新2

在進一步的思考(並感謝約瑟夫他的回答下的進一步討論)似乎是可以應用於此死鬥一些規則:

每道格拉斯·克羅克福德(參見:JS we hardly new Ya匿名功能不應該用「新」的關鍵字,因爲:

  • 這是更快地使用一個物體L iteral。
  • 通過使用new來調用該函數,該對象將保留在無價值的原型對象上。這浪費了記憶,沒有抵消優勢。如果我們不使用新的,我們不會將浪費的原型對象保留在鏈中。 (注:原型來人來電構造函數定義後,和SEAF或「新」的匿名函數被解僱了一個迫在眉睫的不能使用的原型與他們)
  • 它要求使用對象文本更少的代碼。 (雖然真的,但我不同意,因爲我討厭對象文字符號,我更喜歡使用;而不是,因爲它更可讀)
  • 將新的功能直接放在功能前面永遠不是一個好主意。例如,新函數在構造新對象時沒有優勢。

如此看來肉的事情土豆是這樣的:SEAF的是最好var obj = new function() {...};由於速度和更少的開銷(沒有不必要的原型對象)。你必須承受的是,你被迫使用對象字面符號(所以,在你的公共成員之間,而不是);或者在返回對象中維護一個單獨的公共對象列表。

SEAF的都是不可取的,當你正打算爲對象構造函數如預期instanceof將無法​​正常工作,以工作中的作用(參見:creating objects from JS closure: should i use the 「new」 keyword?)。

答:

  • 如果是打算作爲一個Singleton /全球靜態實例,使用SEAF匿名函數。
  • 如果您打算將其作爲Constructor(可能代表多個對象),或者您正在使用.prototype,請使用「標準」函數定義並使用「new」調用。:

    function PseudoClass1() {}

    var PseudoClass2 = function() {};

    var myClass1 = new PseudoClass1();

    var myClass2 = new PseudoClass2();

我不得不說,我不是很滿意這個答案;)我發現.UsingNew模式更在代碼庫中是可讀的,但是由於事實上它比較慢,並且使用更多的內存然後SEAF未使用的原型參考被實例化並留在對象鏈中。

+1

(晚來我知道黨..)很多人在這裏有趣的東西......因爲您更喜歡的UsingNew我不認爲單獨使用未使用的原型是足夠的理由來改變你的方法......這是一個非常小的內存量(爲了比較起見,它比使用模塊模式的編程人員不願意犧牲的數量要小得多原型。) – 2013-05-12 09:18:04

+1

就匿名函數方法而言,如果您將返回變量「self」而不是「fnReturn」稱爲返回變量,則它可能看起來更具可讀性。您甚至可以將任何空對象傳遞給該函數,並將「self」作爲參數;然後從return語句和「self」而不是「this」的使用中獲益,函數的主體將與您的第一個示例相同。 – 2013-05-12 21:29:31

+0

你應該[絕對不要使用'新功能]](http://stackoverflow.com/a/10406585/1048572) – Bergi 2015-01-26 02:11:14

回答

7

一方面,這種模式:

MyNamespace.UsingNew = new function() { 
    var fnPrivate = function() { 

     //what's this in here? 

     return "secrets1"; 
    }; 

    this.property = "value1"; 
    this.method = function() { 

     //what's this in here? 

     return "property = " + this.property + ' ' + fnPrivate(); 
    } 
}; 
  • 使用「新的」關鍵字來創建一個對象,這是使用一個構造函數建模的一個實例。忘記使用「新」,你最終會命名爲功能MyNamespace.UsingNew()而不是一個對象。

  • 這是一個構造函數,而沒有對象的實例(直到你建立了新的使用)。你需要使用「this」來表示它將成爲的對象。它只是問題添加對範圍,特別是當它在你嵌套更多的功能,以及價值「這一」將改變不時(你不會看到它的到來,直到控制檯告訴的你)。熟悉self=thisthat=this保存的「本」的價值?它的otherhand使用這種模式

時幾乎是看到,下一個模式是因爲有所好轉(對我來說):

  • 你不需要用「新的」,因爲它返回一個對象。

  • 不使用「本」,因爲它已經返回一個對象。你甚至不需要「這個」。

另外,我更喜歡建造另一模式是這樣的:

ns.myobj = (function(){ 

    //private 
    var _privateProp = ''; 
    var _privateMeth = function(){}; 

    //public 
    var publicProp = ''; 
    var publicMeth = function(){}; 

    //expose public 
    return { 
     prop:publicProp, 
     meth:publicMeth 
    }; 
}()); 
+0

首先,謝謝你的一個很好的答案! – Campbeln 2012-03-20 22:14:50

+0

原諒我的無知,但即使你忘記了「新」關鍵字並返回了一個函數而不是一個對象,有什麼區別?我猜功能不是很多,但性能(很差)?至於你的前提。方法,你不覺得它是一個保姆。噩夢與底部的回報?我一直使用「.UsingNew」,請參閱:[link](http://code.google.com/p/cn-namespace/source/browse/Cn.Web/js/Cn/Renderer/Form/Form.js ),至於那個=這個問題,因爲我在命名空間中構建,我只是完全解決了所需的功能。我覺得這比痛苦少一點痛苦。返回。 – Campbeln 2012-03-20 22:27:35

+0

看看這個問題,我問如果何時使用「新」http://stackoverflow.com/q/9304473/575527 – Joseph 2012-03-20 22:48:03

2

兩個幾乎是相同的,並應具有相對相同的性能特性。這只是一個風格問題。我個人贊成第二個,但它寫得有點時髦。我會寫它,

MyNamespace.UsingSelfEx = (function() { 
    function fnPrivate() { 
     return "secrets2"; 
    } 
    return { 
     property: "value2"; 
     method: function() { 
      return "property = " + this.property + " " + fnPrivate(); 
     } 
    } 
})(); 

你並不真的需要周圍的功能,但自執行功能的括號通常有他們,讓讀者知道,一開始,這是一個自我執行的功能。

+0

唉,你是對的!自我執行功能通常在他們周圍有「額外」的角色!我很驚訝這似乎是做這個功能的首選方法。當我使用另一種方法時,我偶爾需要「this = that」方法,但是我發現FAR比以任何形式返回對象都要痛苦得多。另外,當我在命名空間中構建時,我通常只是引用我需要使用的this.function的完整名稱空間地址。我確實傾向於將我的「私人」功能設計爲「靜態」,這無疑有助於.UsingNew方法。 – Campbeln 2012-03-20 22:36:52

+0

請參閱:[鏈接](http://code.google.com/p/cn-namespace/source/browse/Cn.Web/js/Cn/Renderer/Form/Form.js)。哦,我還使用了「縮寫」名稱空間(在代碼中用「Cn ._。*」表示)來幫助「rThis = Cn ._。short」作業(而不是「rThis = Cn.Some.Long .Namespace.Path「)。 – Campbeln 2012-03-20 22:37:27

+0

由於這是形成一個名稱空間,並且只有在這顯然只是一種樣式選擇時纔會執行。選擇一個你喜歡的。我更喜歡上述,但那只是一個人的意見。 – chuckj 2012-03-21 00:17:34

0

我已經看到了這一點,我很喜歡它

var MyThing = (function(){ 

    function MyThing(args){ 
    } 

    MyThing.prototype = { 
     prototypeMethod: function() {} 
    }; 

    return MyThing; 
})(); 

你也可以做到這一點

MyThing.create = function(args){ 
    return new MyThing(args); 
} 

它通常被封閉在一個又一個自我調用函數。 爲了避免命名衝突。

(function({ 

})(window); 

window對象被作爲參數傳遞, 將其分配到的上範圍。

window.MyThing = MyThing; 

在這個例子中,你可以使用,靜態變量,私營等