死斗:自执行的匿名航班吗功能的“新功能”

问题描述:

答案在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://*.com/a/10406585/1048572) – Bergi 2015-01-26 02:11:14

一方面,这种模式:

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://*.com/q/9304473/575527 – Joseph 2012-03-20 22:48:03

两个几乎是相同的,并应具有相对相同的性能特性。这只是一个风格问题。我个人赞成第二个,但它写得有点时髦。我会写它,

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

我已经看到了这一点,我很喜欢它

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; 

在这个例子中,你可以使用,静态变量,私营等