In-depth understanding of JavaScript module patterns

Source: Internet
Author: User
Tags shallow copy

Module mode is a common encoding pattern for JavaScript. This is a general understanding, but there are some advanced applications

Did not get much attention. In this article, I'll review the basics, browse some good advanced techniques, and even I think it's native based.

Basic Knowledge First we start with a simple overview of model patterns. Three years ago, Eric Miraglia (YUI) 's blog post made model patterns known. If you are already familiar with model mode, you can read the "Advanced mode" directly. Anonymous closures This is the basis for all possible and the best features of JavaScript. We will simply create an anonymous function and execute it immediately. All function internal code is within the closure (closure). It provides the private and state of the entire application life cycle.

    1. (function () {
    • ... all vars and functions is in this scope only
    • Still maintains access to all globals
    • }());
    • ?

Note the () around the anonymous function. This is the language requirement. The keyword function is generally considered a function declaration, including () is a function expression. Introduce global

JavaScript has a feature called the implicit Global. When you use a variable name, the interpreter looks backwards from the scope for the variable declaration. If not found, the variable is assumed to be in the global (can be called globally later). If it is allocated, it is created globally when it does not already exist. This means that it is easy to use global variables in anonymous functions. Unfortunately, this can cause code to be difficult to manage, and it's not easy to differentiate (to people) which variables are global. Fortunately, the anonymous function has a good choice. Global variables are passed as parameters to anonymous functions. Bringing them into our code is both clearer and faster than using the implicit global. Here is an example:

    1. (Function ($, YAHOO) {
    • The current domain has permission to access global jquery ($) and Yahoo
    • } (JQuery, YAHOO));
    • ?

Module exit

Sometimes you don't just want to use global variables, but you need to declare them (global invocation of the module). We use the return values of anonymous functions to easily output them. This completes the basic module mode. Here is a complete example:

    1. var MODULE = (function () {
    • var my = {},
    • privatevariable = 1;
    • function Privatemethod () {
    • // ...
    • }
    • My.moduleproperty = 1;
    • My.modulemethod = function () {
    • // ...
    • };
    • return my;
    • }());
    • ?

Notice that we have declared a global module, with two public properties: Method Module.modulemethod and Property Module.moduleproperty. Furthermore, the closure of the anonymous function maintains a private internal state. At the same time learning the content above, we can easily introduce the global variables needed, and output to global variables. Advanced Mode

For many users, the above is not enough, we can use the following pattern to create a powerful, extensible structure. Let's use module modules, one to continue. Expansion

One limitation of module mode is that the entire module must be in one file. Anyone is aware of the need to split long code into different files. Fortunately, we have a good way to expand the module. (in the extension file) first we introduce the module (from the Global), add the attribute to him, and then output him. The following is an example of an expansion module:

    1. var MODULE = (function (my) {
    • My.anothermethod = function () {
    • The previous module returns the My object as the global output, so the parameter module for this anonymous function is my in the module anonymous function above.
    • };
    • return my;
    • } (MODULE));
    • ?

We use the VAR keyword again to maintain consistency, although it's not really necessary. After the code executes, the module obtains a new public method, Module.anothermethod. The extension file does not affect the private internal state of the module. loosely coupled expansion

The above example requires that we create the module first and then expand it, which is not always necessary. The best way to improve JavaScript application performance is to load scripts asynchronously. Thus we can create flexible multi-part modules that can be loaded without order and loosely coupled to augment. Each file should have the following structure:

    1. var MODULE = (function (my) {
    • Add Capabilities ...
    • return my;
    • } (MODULE | | {}));
    • ?

In this mode, the Var statement is necessary to mark the introduction of a nonexistent when it is created. This means that you can load all the module files at the same time as Labjs without being blocked. Tight Coupling expansion

Although loose coupling is good, there are some limitations on the module. Most importantly, you cannot safely overwrite module properties (because there is no loading order). The module properties defined by other files cannot be used when initializing (but you can run after initialization). Tight-coupled expansion implies a set of loading orders, but is allowed to overwrite. Here is an example (to augment the originally defined module):

    1. var MODULE = (function (my) {
    • var old_modulemethod = My.modulemethod;
    • My.modulemethod = function () {
    • Method override, have access to old through Old_modulemethod ...
    • };
    • return my;
    • } (MODULE));
    • ?

We overwrite the Module.modulemethod, but still maintain a private internal state. Cloning and inheritance

    1. var Module_two = (function (old) {
  • var my = {},
  • Key
  • For (Key-in-old) {
  • if (Old.hasownproperty (key)) {
  • My[key] = Old[key];
  • }
  • }
  • var super_modulemethod = Old.modulemethod;
  • My.modulemethod = function () {
  • Override method on the clone, access to super through Super_modulemethod
  • };
  • return my;
  • } (MODULE));
  • ?

This approach may be the least flexible. He can achieve ingenious combinations, but at the expense of flexibility. As I wrote, the object's property or method is not a copy, but a two reference to an object. Modifying one will affect the other. This may keep the properties of a recursive clone object fixed, but cannot be fixed, except with an eval method. However, I have fully included the module. (A shallow copy is actually done). Cross-file private status

A module that splits into several files has a serious flaw. Each file has its own private state and does not have access to the private state of the other file. This can be fixed. Here is an example of a loosely coupled extension that keeps a private state between different extensions:

    1. var MODULE = (function (my) {
  • var _private = My._private = My._private | | {},
  • _seal = My._seal = My._seal | | function () {
  • Delete my._private;
  • Delete my._seal;
  • Delete my._unseal;
  • },//after the module is loaded, call to remove access to _private
  • _unseal = My._unseal = My._unseal | | function () {
  • My._private = _private;
  • My._seal = _seal;
  • My._unseal = _unseal;
  • };//the module before loading, open access to the _private to enable the operation of the extended section on private content
  • Permanent access to _private, _seal, and _unseal
  • return my;
  • } (MODULE | | {}));
  • ?

Any file can be set in the local variable _private, he will take immediate effect on other extensions (that is, all the expanded private state is saved in the _private variable and is my._private output). The module is fully loaded, and the application calls the Module._seal () method to block the read of the private property (Kill the My._private output). If the module needs to be expanded later, it will have a private method. Call the Module._unseal () method before loading the extension file (restore my._private, external restore operation permissions). After loading, call again seal (). This pattern has been working with me so far and I haven't seen anywhere else to do so. I think this pattern is very useful and worth writing on. Sub-module

The final advanced mode is actually the simplest. There are many good ways to create sub-modules. is the same as creating a parent module:

    1. Module.sub = (function () {
    • var my = {};
    • is a multi-level namespace
    • return my;
    • }());
    • ?

Although it's very simple, I'll mention it. The submodule has all the functions of the normal module, including the expansion and the private state. Summary

Most advanced modes can be combined into more useful patterns. If I were to propose a design pattern for a complex application, I would combine loose coupling, private state, and submodule. I haven't touched on performance here, but I have a little suggestion: The module mode is performance gain. He simplifies a lot and accelerates code downloads. Loose coupling can be downloaded without blocking parallel, which is equivalent to increasing the download speed. It might be a bit slower to initialize than other methods, but it's worth the tradeoff. As long as the global correct introduction, there will be no loss of performance, and may also be due to local variables and fewer references, to speed up the loading of sub-modules. Finally, an example dynamically loads the submodule into the parent module (dynamic creation). This is not a private state, in fact, plus is very simple. This code allows the entire complex to be divided into the code core and its sub-modules, such as parallel loading completely.

    1. var UTIL = (function (parent, $) {
    • var my = Parent.ajax = Parent.ajax | | {};
    • My.get = function (URL, params, callback) {
    • OK, so I ' m cheating a bit:)
    • Return $.getjson (URL, params, callback);
    • };
    • etc...
    • return parent;
    • } (UTIL | | {}, jQuery));
    • ?

Transferred from: http://www.oschina.net/translate/javascript-module-pattern-in-depth

In-depth understanding of JavaScript module patterns

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.