我一直在研究为我的团队提出标准化的Javascript编码风格。现在大多数资源都推荐涉及闭包的“模块”模式,例如:
var Module = function() {
someMethod = function() { /* ... */ };
return {
someMethod: someMethod
};
}();
并像Module.someMethod();
一样调用它。这种方法似乎只适用于在传统OOP上下文中是静态的方法,例如用于获取/保存数据的存储库类,用于发出外部请求的服务层等。除非我遗漏了某些内容,否则模块模式不适用于通常需要传递给服务方法/从服务方法传递到UI粘合代码的数据类(思考DTO)。
我看到的一个常见好处是,您可以在Javascript中使用模块模式获得真正的私有方法和字段,但这也可以实现以及能够具有静态或具有类似于此的“经典”Javascript样式的实例方法:
myClass = function(param) {
// this is completely public
this.publicProperty = 'Foo';
// this is completely private
var privateProp = param;
// this function can access the private fields
// AND can be called publicly; best of both?
this.someMethod = function() {
return privateProp;
};
// this function is private. FOR INTERNAL USE ONLY
function privateMethod() {
/* ... */
};
}
// this method is static and doesn't require an instance
myClass.staticMethod = function() { /* ... */ };
// this method requires an instance and is the "public API"
myClass.prototype.instanceMethod = function() { /* ... */ };
所以我想我的问题是什么使模块模式比传统风格更好?它有点清洁,但这似乎是唯一明显的好处;事实上,传统风格似乎提供了提供真正封装的能力(类似于真正的OOP语言,如Java或C#),而不是简单地返回一组静态方法。
我有什么遗失的吗?
答案 0 :(得分:2)
模块模式可用于创建原型以及:
var Module = function() {
function Module() {};
Module.prototype.whatever = function() {};
return Module
}();
var m = new Module();
m.whatever();
正如另一张海报所说,干净的全球命名空间就是它的原因。然而,另一种实现此目的的方法是使用AMD模式,这也解决了依赖管理等其他问题。它还将所有东西都包裹在各种各样的封闭中。这是一个很棒的Introduction to AMD,代表异步模块定义。
我还建议阅读JavaScript Patterns,因为它完整地涵盖了各种模块模式的原因。
答案 1 :(得分:2)
上面的模块模式毫无意义。您所做的就是使用一个闭包来返回带有原型的构造函数。您可以通过以下方式实现相同目标:
function Module() {};
Module.prototype.whatever = function() {};
var m = new Module();
m.whatever();
实际上,您可以使用相同的输出保存一个对象(闭包)。
我对模块模式的另一种看法是,如果你将它用于私有封装,你只能轻松地使用单例而不是具体的类。要创建具有私有数据的具体类,最终会包含两个闭包器,这会变得很难看。我也同意,当它们可见时,能够调试下划线伪私有属性要容易得多。 “如果某人错误地使用你的课程会怎么样”的整个概念从来都不合理。制作一个干净的公共API,记录它,如果人们没有正确地遵循它,那么你的团队中就有一个糟糕的程序员。 Javascript隐藏变量(可以在Firefox中使用eval发现)所需的工作量不值得JS的典型用法,即使对于大中型项目也是如此。人们不会窥探你的物体来学习它们,他们会阅读你的文档。如果你的文档很好(例如使用JSDoc)那么他们就会坚持下去,就像我们使用我们需要的每个第三方库一样。我们不会“篡改”jQuery或YUI,我们只是信任并使用公共API而不关心它下面使用的方式或内容。
答案 2 :(得分:1)
您忘记提及模块模式的另一个好处是,它在全局命名空间中促进了更少的混乱,即人们在说“不污染全局命名空间”时所引用的内容。当然,你可以用经典方法做到这一点,但似乎在匿名函数之外创建对象会更容易在全局命名空间中创建这些对象。
换句话说,模块模式可以促进自包含的代码。模块通常会将一个对象推送到全局命名空间,并且与模块的所有交互都会通过此对象。这就像是一种“主要”方法。
全局命名空间中的较少混乱是好的,因为它减少了与其他框架和javascript代码冲突的可能性。