简体   繁体   English

Javascript模块模式的好处是什么?

[英]What is the benefit of the Javascript Module Pattern?

I have been doing research to come up with a standardized Javascript coding style for my team. 我一直在研究,以为我的团队提出一种标准化的Javascript编码样式。 Most resources now recommend the "Module" pattern that involves closures, such as this: 现在,大多数资源都建议使用涉及闭包的“模块”模式,例如:

var Module = function() { 

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

    return { 
        someMethod: someMethod
    };

}();

and invoke it like Module.someMethod(); 并像Module.someMethod();一样调用它Module.someMethod(); . This approach seems to only work with methods that would be static in a traditional OOP context, for example repository classes to fetch/save data, service layers to make outside requests, and the like. 这种方法似乎仅适用于在传统OOP上下文中是静态的方法,例如用于获取/保存数据的存储库类,用于发出外部请求的服务层等。 Unless I missed something, the module pattern isn't intended to be used with data classes (think DTOs) that would typically need to be passed to/from the service methods to the UI glue code. 除非我错过了什么,否则模块模式不打算与通常需要在服务方法之间传递或从服务方法传递到UI粘合代码的数据类(例如DTO)一起使用。

A common benefit I see cited is that you can have true private methods and fields in Javascript with the module pattern, but this can also be achieved along with being able to have static or instance methods with the "classical" Javascript style similar to this: 我看到的一个共同好处是,您可以在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() { /* ... */ };

So I guess my question is what makes the Module Pattern better than the traditional style? 所以我想我的问题是什么使模块模式比传统样式更好? It's a bit cleaner, but that seems to be the only benefit that is immediately apparent; 它比较干净,但这似乎是唯一显而易见的好处。 in fact, the traditional style seems to offer the ability to provide real encapsulation (similar to true OOP languages like Java or C#) instead of simply returning a collection of static-only methods. 实际上,传统样式似乎提供了真正的封装(类似于像Java或C#这样的真正的OOP语言)的能力,而不是简单地返回纯静态方法的集合。

Is there something I'm missing? 有什么我想念的吗?

Module Pattern can be used to create prototypes as well see: 模块模式还可用于创建原型,请参见:

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

As the other poster said the clean global namespace is the reason for it. 正如另一位发布者所说,干净的全局名称空间是其原因。 Another way to achieve this however is to use the AMD pattern, which also solves other issues like dependency management. 但是,实现此目标的另一种方法是使用AMD模式,该模式还解决了其他问题,如依赖管理。 It also wraps everything in a closure of sorts. 它还将所有内容包装在某种封闭形式中。 Here's a great Introduction to AMD which stands for Asynchronous Module Definition. 这是AMD的出色介绍 ,代表异步模块定义。

I also recommend reading JavaScript Patterns as it thoroughly covers the reasons for various module patterns. 我还建议您阅读JavaScript模式,因为它全面介绍了各种模块模式的原因。

The module pattern above is pointless. 上面的模块模式毫无意义。 All you are doing is using one closure to return a constructor with prototype. 您要做的就是使用一个闭包返回带有原型的构造函数。 You could have achieved the same with: 您可以通过以下方法实现相同的目的:

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

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

In fact you would have saved one object (the closure) from being created, with the same output. 实际上,您已经保存了一个对象(闭包)被创建的情况,并且具有相同的输出。

My other beef with the module pattern is it if you are using it for private encapsulation, you can only use it easily with singletons and not concrete classes. 与模块模式有关的另一点是,如果您将其用于私有封装,则只能将其轻松用于单例而不是具体类。 To create concrete classes with private data you end up wrapping two closers, which gets ugly. 要使用私有数据创建具体的类,您最终要包装两个封闭器,这很丑陋。 I also agree that being able to debug the underscore pseudo-private properties is a lot easier when they are visible. 我也同意,在下划线伪私有属性可见时,能够对其进行调试要容易得多。 The whole notion of "what if someone uses your class incorrectly" is never justified. 整个概念“如果有人错误地使用了您的班级怎么办”是没有道理的。 Make a clean public API, document it, and if people don't follow it correctly, then you have a poor programmer in your team. 制作一个干净的公共API,对其进行文档化,然后,如果人们不正确地遵循它,那么您的团队中的程序员将很糟糕。 The amount of effort required in Javascript to hide variables (which can be discovered with eval in Firefox) is not worth the typical use of JS, even for medium to large projects. Java中隐藏变量所需的工作量(可以在Firefox中用eval发现)不值得JS的典型用法,即使对于大中型项目也是如此。 People don't snoop around your objects to learn them, they read your docs. 人们不会窥探您的对象来学习它们,而是阅读您的文档。 If your docs are good (example using JSDoc) then they will stick to it, just like we use every 3rd party library we need. 如果您的文档不错(例如使用JSDoc的示例),那么它们会坚持使用,就像我们使用所需的每个第三方库一样。 We don't "tamper" with jQuery or YUI, we just trust and use the public API without caring too much how or what it uses underneath. 我们不会“篡改” jQuery或YUI,我们只是信任并使用公共API,而无需过多关注其底层使用的方式或用途。

Another benefit you forgot to mention to the module pattern, is that it promotes less clutter in the global namespace, ie, what people refer to when they say "don't pollute the global namespace". 您忘记提及模块模式的另一个好处是,它在全局名称空间中减少了混乱,即人们说“不污染全局名称空间”时所指的内容。 Sure you can do that in your classical approach, but it seems creating objects outside of anonymous functions would lend more easily to creating those objects in the global namespace. 当然,您可以使用传统方法来做到这一点,但是在匿名函数之外创建对象似乎更容易在全局名称空间中创建这些对象。

In other words, the module pattern promotes self contained code. 换句话说,模块模式促进了自包含代码。 A module will typically push one object onto the global namespace, and all interaction with the module goes through this object. 一个模块通常会将一个对象推送到全局名称空间,并且与该模块的所有交互都将通过该对象。 It's like a "main" method. 这就像一个“主要”方法。

Less clutter in the global namespace is good, because it reduces the chances of collisions with other frameworks and javascript code. 全局名称空间中的混乱情况比较好,因为它减少了与其他框架和javascript代码发生冲突的机会。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM