JavaScript模块模式有什么好处?

8

我一直在研究为我的团队制定标准化的Javascript编码风格。现在大多数资源推荐使用"模块(Module)"模式,该模式涉及闭包,例如:

var Module = function() { 

    someMethod = function() { /* ... */ };

    return { 
        someMethod: someMethod
    };

}();

这种方法可以像这样调用:Module.someMethod();。这种方法似乎仅适用于在传统OOP上下文中将会是静态的方法,例如存储库类以获取/保存数据、服务层以进行外部请求等。除非我漏掉了什么,否则模块模式并不适用于数据类(例如 DTO),这些类通常需要从服务方法传递到 UI 粘合代码。

我经常听到人们提到的一个共同的好处是,通过模块模式,您可以在 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() { /* ... */ };

所以我想问的是,模块模式相比传统风格有什么优势?它可能更加简洁,但这似乎是唯一显而易见的好处;事实上,传统风格似乎提供了真正的封装能力(类似于Java或C#等真正的面向对象语言),而不仅仅是返回一组仅限于静态方法的集合。

我有什么遗漏吗?


Module模式可以用于创建原型,如下所示: var Module = function() { function Module() {}; Module.prototype.whatever = function() {}; return Module }(); - Jamund Ferguson
1
如果您正在定义单例,则使用静态方法或实例方法并不重要。事实上,我更喜欢使用静态版本,因为这样在使用回调函数中的某些函数时,我就不必担心弄乱“this”的内容。 - hugomg
3个回答

2

模块模式可以用于创建原型,如下所示:

var Module = function() { 
  function Module() {};
  Module.prototype.whatever = function() {};
  return Module
}();
var m = new Module();
m.whatever();

正如其他帖子所说,干净的全局命名空间是其原因。然而,实现这一点的另一种方法是使用AMD模式,它还解决了依赖管理等其他问题。它也将所有内容包装在某种闭包中。这里有一个很棒的AMD介绍,它代表异步模块定义。
我还建议阅读JavaScript模式,因为它详细介绍了各种模块模式的原因。

2

上面的模块模式是没有意义的。你所做的只是使用一个闭包来返回一个带有原型的构造函数。你可以通过以下方式实现相同的效果:

function Module() {};
Module.prototype.whatever = function() {};

var m = new Module();
m.whatever();

实际上,你可以通过不创建闭包来达到相同的输出,从而节省了一个对象。
我对模块模式的另一个不满是,如果你将其用于私有封装,那么只能轻松地与单例一起使用,而不能与具体类一起使用。要创建具有私有数据的具体类,你需要包装两个闭包,这会变得很丑陋。我也同意,当伪私有属性可见时,更容易调试它们。整个“如果有人不正确使用你的类”的概念是没有道理的。创建一个清晰的公共 API,记录它,如果人们没有正确遵循它,那么你的团队中就有一个糟糕的程序员。在 JavaScript 中隐藏变量所需的努力(在 Firefox 中可以通过 eval 发现)甚至对于中型到大型项目也不值得。人们不会窥探你的对象来学习它们,他们阅读你的文档。如果你的文档很好(例如使用 JSDoc),那么他们会坚持使用它,就像我们使用每个需要的第三方库一样。我们不会“篡改” jQuery 或 YUI,我们只是信任并使用公共 API,而不太关心它下面使用了什么或者怎么使用。

1
另一个你忘记提到的模块模式的好处是,它促进了全局命名空间中的少量混乱,即人们所说的“不要污染全局命名空间”。当然,你可以在传统方法中做到这一点,但似乎在匿名函数之外创建对象更容易将这些对象创建在全局命名空间中。
换句话说,模块模式促进了自包含代码。一个模块通常会将一个对象推送到全局命名空间中,并且与模块的所有交互都通过此对象进行。就像一个“主”方法。
全局命名空间中的少量混乱很好,因为它减少了与其他框架和JavaScript代码发生冲突的机会。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接