在UPDATE 2 / ANSWER
中回答下面的内容感谢Joseph帮助我找到答案(即使我不喜欢它)。
原始问题
在使用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;
})();
更新
似乎像jQuery一样,所有酷孩子都在使用&#34;自我执行匿名函数&#34; (SEAF)!但我只是没有得到这个,因为我发现使用.UsingNew方法更清洁,因为你在定义中暴露公共函数(而不是在需要单独维护或被迫使用内联对象表示法。)
不需要的论据&#34;那=&#34;由于种种原因,我不能为我喝水:
现在......我想我的开发风格可能会使.UsingNew模式更容易管理。我的私人&#34;功能几乎总是&#34;静态&#34;在本质上,所以我需要传递上下文(取代&#34;这个&#34;)的需要。我也养成了使用&#34;缩写&#34;的习惯。命名空间,所以当我确实需要访问&#34;这个&#34;我只是通过&#34;缩写&#34;来引用完整的对象。命名空间而不是通过它的完整路径。 E.G:
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 :
经过进一步反思(并且由于在他的回答下与约瑟夫进行了长时间的讨论),似乎有一些规则可以适用于这个死亡事件:
Per Douglas Crockford(参见:JS we hardly new Ya)匿名函数不应该使用&#34; new&#34;关键字因为:
所以看来问题的关键是:由于速度和较少的开销(没有不需要的原型对象),SEAF优于var obj = new function() {...};
。您必须经历的是,您被迫使用对象文字符号(因此,而不是;在您的公共成员之间)或维护一个单独的公共对象列表。返回对象。
instanceof
将无法按预期工作(请参阅:creating objects from JS closure: should i use the “new” keyword?)。
解答:
如果您打算将其用作Constructor
(可能代表多个对象)或使用.prototype,请使用&#34;标准&#34;函数定义并使用&#34; new&#34 ;,例如:
function PseudoClass1() {}
var PseudoClass2 = function() {};
var myClass1 = new PseudoClass1();
var myClass2 = new PseudoClass2();
我不得不说,我对这个答案不满意;)我发现.UsingNew模式在代码库中更具可读性,但由于未使用的原型引用是事实,它比SEAF更慢并且使用更多内存实例化并留在对象链中。
答案 0 :(得分:8)
首先,这种模式:
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();
}
};
使用“new”关键字创建对象的实例,该实例使用构造函数建模。忘记使用“新”,你最终会命名为一个函数MyNamespace.UsingNew()
而不是一个对象。
它是一个构造函数,而不是一个对象的实例(直到你用new构建它)。你需要使用“this”来描述它将成为的对象。它只是在范围中添加问题,特别是当你在其中嵌入更多函数时,“this”的值会不时变化(并且在控制台告诉你之前你不会看到它)。熟悉self=this
或that=this
以保存“this”的值?使用这种模式时几乎可以看到它
另一方面,下一个模式对我来说有点好(因为我):
您不需要使用“new”,因为它返回一个对象。
不使用“this”,因为它已经返回一个对象。你甚至不需要“这个”。
另外,我更喜欢用这种方式构建其他模式:
ns.myobj = (function(){
//private
var _privateProp = '';
var _privateMeth = function(){};
//public
var publicProp = '';
var publicMeth = function(){};
//expose public
return {
prop:publicProp,
meth:publicMeth
};
}());
答案 1 :(得分:2)
两者几乎相同,应具有相对相同的性能特征。这只是一种风格问题。我个人赞成第二个,但它写得有点时髦。我会写的,
MyNamespace.UsingSelfEx = (function () {
function fnPrivate() {
return "secrets2";
}
return {
property: "value2";
method: function () {
return "property = " + this.property + " " + fnPrivate();
}
}
})();
你真的不需要围绕这个功能的parens,但是自动执行功能通常会有它们,并且让读者在开始时知道这是一个自我执行的功能。
答案 2 :(得分: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;
在这个例子中,您可以使用静态变量,私有等。