Reprinted translation article: JavaScript Module pattern:in-dept

Source: Internet
Author: User
Tags closure

# JavaScript Module pattern:in-depth

# reprinted translation article: JavaScript Module pattern:in-depth
* Original *:http://www.adequatelygood.com/javascript-module-pattern-in-depth.html

Module mode is a common JS development coding mode. Generally speaking, it's well understood, but there are some advanced applications that don't get much attention. In this article, I'll review the basics and introduce some really great advanced topics, including one I think is extremely primitive.

# # The Basics
We will start with a simple overview of a module pattern. Module mode, from three years ago Yui's Eric Miraglia published in his blog began, it is known to us. If you are already familiar with module mode, skip to "Advanced Mode" (Patterns).

# # # Anonymous Closures (anonymous closures)
This is the basic structure that makes everything possible, and it is indeed one of the greatest features of JavaScript's uniqueness. We simply create an anonymous function and execute it immediately. All the code in the function, which exists in a closure, provides a private environment and state for the entire application run life cycle.

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

It should be noted that the anonymous function is wrapped by a parenthesis "()". This is a linguistic requirement because the block of statements starting with the Function keyword is always considered to be the declaration of functions, and "()" is used to make it a function expression.

# # Global Import
JavaScript has a feature called "implied Globals". Whenever a variable name is used, the parser will backtrack through the entire scope chain to find a "var" declaration statement for the variable name. If not found, this variable is considered to be a global variable. If the variable is already assigned and is global, this global variable is created. This means that it is easy to use or create global variables in an anonymous closure. Unfortunately, this will cause code to be difficult to manage because the global variables in a given file are not particularly obvious to the coder.

Fortunately, our anonymous function provides a simple choice. By passing the global variables as parameters to the Gold anonymous function, we import the global variables into our code, which is faster and clearer than the "implied globals". Here is an example:
```
(Function ($, YAHOO) {
Now has access to Globals JQuery (as $) and YAHOO. This code
} (JQuery, YAHOO));
```

# # # Module Export
Sometimes you don't want to use them right away, but you want to declare them. We can easily use the return value of the anonymous function to output them. Doing this will complete the basic module pattern. The following is a complete example
```
var MODULE = (function () {
var my = {},
privatevariable = 1;

function Privatemethod () {
// ...
}

My.moduleproperty = 1;
My.modulemethod = function () {
// ...
};

return my;
}());
```
It should be noted that we have declared a global module called module, which contains two public properties: A method named Module.modulemethod, a variable named Module.moduleproperty. In addition, it uses anonymous functions in closures to keep the internal state private. Furthermore, we can easily import the required global modules (variables) using the patterns we have learned above.

# # Advanced Patterns
While the above description is sufficient for many of our uses, we can also make this pattern go further and create some very powerful, extensible structures. Let's continue to use them as module modules, one after another.

# # Augmentation

One limitation of the module mode so far is that the entire module must be in one file. All who work on this huge code base must understand the divisions that exist in this complex file. Fortunately, we have a good solution for expansion modules. First, we import the module, then add the properties, and finally export. Here is an example that expands the module modules above:
```
var MODULE = (function (my) {
My.anothermethod = function () {
Added method ...
};

return my;
} (MODULE));
```

We re-use the var keyword for consistency, even if it is not required. After running this code, our module will get a new public method named Module.anothermethod. This extension file will also maintain its own private internal state and import modules.

# # # Loose augmentation (Loose extension)

Our example above requires that we first create the initialization module and then expand it, but we are not really necessary. One of the best things for a JavaScript application to render is the asynchronous loading of the script. With this loose extension, we can create flexible, multi-part modules that can be loaded in any order. Each file should contain the following structure:
```
var MODULE = (function (my) {
Add Capabilities ...

return my;
} (MODULE | | {}));
```


In this mode, the VAR keyword is always required. It should be noted that the introduced module will be created automatically if it does not exist. This means that you can use some tools, such as LABJS, to load your module files in parallel without blocking.

# # # Tight augmentation (Strictly extended)

While the loose extension is great, it still has some limitations on your module. The most important thing is that you cannot safely override the module properties. You also cannot use module properties from other files during initialization (although the run time after initialization is complete). Strict scaling means a set of sequential loads, but it allows rewriting. Here is a simple example (extension of the original module module):

var MODULE = (function (my) {
var old_modulemethod = My.modulemethod;

My.modulemethod = function () {
Method override, have access to old through Old_modulemethod ...
};

return my;
} (MODULE));

Here we rewrite the Module.modulemethod method, but maintain a link to the original method, if necessary.


# # # Cloning and Inheritance (clones and inheritance)
```
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 mode is probably the least flexible option. It allows for some neat combinations, but at the expense of flexibility. As I wrote before, objects or functions that are not actually copied will have two associations for an object. Changing one will then change the other. For objects, this problem can be fixed by a recursive cloning process, but cannot be repaired for function, perhaps using eval ().
But for the sake of completeness, I have included it.

# # # Cross-file Private State

For modules that are split in multiple files, a serious limitation is that each file maintains its own private state and does not have access to the private environment of the other files. This can be solved. Here is an example of a loose expansion module that holds a private environment spanning all extensions:
```
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;
},
_unseal = My._unseal = My._unseal | | function () {
My._private = _private;
My._seal = _seal;
My._unseal = _unseal;
};

Permanent access to _private, _seal, and _unseal

return my;
} (MODULE | | {}));
```

Any file can set properties on its own local variable _private, and it will take effect immediately. Once this module is loaded, the application should call the Module._seal () method, which blocks external access to the internal _private. If this module is added again, in its future application life cycle, an internal method of any file can call the _unseal () method before loading a new file, and then call the _seal () method again after it executes. This pattern was in my mind when I was working today, and I have never seen this usage elsewhere. I think this is a super useful pattern and it has in fact proved to be well worth writing.


# # Sub-modules

Our last advanced mode is actually the simplest one. There are many good examples of creating sub-modules. Just like creating normal mode:
```
Module.sub = (function () {
var my = {};
// ...

return my;
}());
```

Although it may be relatively shallow, I still think it deserves to be included (our model). Sub-modules contain advanced features for all common modules, including extended and private states.

# # Conclusions (conclusion)

All advanced modules can be combined with each other to create more useful patterns. If I had to come up with a route for designing complex applications, I would synthesize loose augmentation (loose extension), private state (private status), and Sub-modules (submodule) of these three.

I'm not going to go into it here, but I'll give you some quick conclusions: this pattern is doing very well. It compresses well and makes the code load faster. The use of loose extensions makes it easy to load non-blocking loads, which also speeds up download speeds. The initialization time may be slower than other modes, but it's worth the tradeoff. As long as the global variables have been properly imported, the performance of the runtime should not have any problems, and in the submodule because of the reduction of the association chain through local variables, the speed will be much faster.


As an end, here is an example of a submodule dynamically loading itself as a parent (created when it does not exist). I've abandoned the simplicity of the private environment here, but it's also a single room to include. This code pattern allows the entire complex structure of the code base itself, including submodules and all other things to load in parallel.
```
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));
```
I hope this have been useful, and please leave a comment to share your thoughts. Now, go forth and write better, more modular javascript!

Reprinted translation article: JavaScript Module pattern:in-dept

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.