In-depth understanding of the JavaScript module Mode

Source: Internet
Author: User

Http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth.

The module mode is a common JavaScript encoding mode. This is a general understanding, but some advanced applications have not received much attention. In this article, I will review my basic knowledge, browse some good advanced skills, and even I think it is a native basis.

Basic knowledge

First, let's give a brief overview of the model. Three years ago, Eric Miraglia (YUI)'s blog post made model models well known. If you are familiar with the model mode, you can directly read "advanced mode ".

Anonymous Closure

This is the foundation for everything to become possible and the best feature of JavaScript. We will simply create an anonymous function and execute it immediately. The internal code of all functions is in the closure. It provides the private and state of the entire application lifecycle.

  1. (Function (){
  2. //... All vars and functions are in this scope only
  3. // Still maintains access to all globals
  4. }());

Copy code

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

Introduce Global

JavaScript has a feature called implicit global. When a variable name is used, the interpreter looks for the variable declaration from the scope to the back. If not found, the variable is assumed to be global (which can be called globally later ). If it is allocated for use, it is created globally when it does not exist. This means that it is easy to use global variables in anonymous functions. Unfortunately, this will make the code difficult to manage, and it is not easy to distinguish (for humans) which variable is global in the file.

Fortunately, there is another good option for anonymous functions. The global variables are passed to the anonymous function as parameters. Introducing them into our code is clearer and faster than using a hidden global. The following is an example:

  1. (Function ($, YAHOO ){
  2. // The current domain has the permission to access global jQuery ($) and YAHOO
  3. } (JQuery, YAHOO ));

Copy code

Module egress

Sometimes you not only want to use global variables, but you need to declare them first (Global calls of modules ). We use the returned values of anonymous functions to output them easily. This completes the Basic module mode. The following is a complete example:

  1. Var MODULE = (function (){
  2. Var my = {},
  3. PrivateVariable = 1;
  4. Function privateMethod (){
  5. //...
  6. }
  7. My. moduleProperty = 1;
  8. My. moduleMethod = function (){
  9. //...
  10. };
  11. Return my;
  12. }());

Copy code

Note: We declare a global MODULE with two public attributes: method MODULE. moduleMethod and attribute MODULE. moduleProperty. In addition, the closure of the anonymous function maintains the private internal state. At the same time, we can easily introduce the required global variables and output them to global variables.

Advanced Mode

For many users, the above is still insufficient. We can use the following models to create a powerful and scalable structure. Let's use the MODULE to continue one by one.

Expansion

One limitation of the module mode is that the entire module must be in a file. Anyone knows the necessity of separating long code into different files. Fortunately, we have a good way to expand the module. (In the expansion file) First we introduce the module (from the global), add attributes to it, and then output it. The following is an example of the expansion module:

  1. Var MODULE = (function (my ){
  2. My. anotherMethod = function (){
  3. // The previous MODULE returns the my object as the global output. Therefore, the MODULE parameter of this anonymous function is
  4. };
  5. Return my;
  6. } (MODULE ));

Copy code

We use the var keyword again to maintain consistency, though not necessary. After the code is executed, the MODULE obtains a new public method MODULE. anotherMethod. The expanded file does not affect the private internal status of the module.

Loosely Coupled Expansion

In the above example, we need to first create a module and then expand it. This is not always necessary. The best operation to improve the performance of JavaScript applications is to load scripts asynchronously. Therefore, we can create flexible modules and load them unsequentially to expand with loose coupling. Each file should have the following structure:

  1. Var MODULE = (function (my ){
  2. // Add capabilities...
  3. Return my;
  4. } (MODULE | {}));

Copy code

In this mode, the var statement is required to mark that it does not exist when it is introduced. This means that you can load all module files at the same time as LABjs without being blocked.

Tightly coupled Expansion

Although the loose coupling is good, there are some limitations on the module. Most importantly, you cannot safely overwrite module attributes (because there is no loading order ). The module attributes defined by other files cannot be used during initialization (but you can run them after initialization ). Tightly coupled expansion means a set of loading sequence, but overwriting is allowed. The following is an example (expanding the MODULE originally defined ):

  1. Var MODULE = (function (my ){
  2. Var old_moduleMethod = my. moduleMethod;
  3. My. moduleMethod = function (){
  4. // Method override, has access to old through old_moduleMethod...
  5. };
  6. Return my;
  7. } (MODULE ));

Copy code

The MODULE. moduleMethod we override remains in the private internal state.

Cloning and inheritance

  1. Var MODULE_TWO = (function (old ){
  2. Var my = {},
  3. Key;
  4. For (key in old ){
  5. If (old. hasOwnProperty (key )){
  6. My [key] = old [key];
  7. }
  8. }
  9. Var super_moduleMethod = old. moduleMethod;
  10. My. moduleMethod = function (){
  11. // Override method on the clone, access to super through super_moduleMethod
  12. };
  13. Return my;
  14. } (MODULE ));

Copy code

This method may be the least flexible. He can achieve clever combinations, but sacrifices flexibility. As I wrote, the attributes or methods of an object are not copied, but two references of an object. Modifying one will affect others. This may keep the attributes of recursive clone objects fixed, but not the fixed method, except for the eval method. However, I have completely included the module. (In fact, it is a shallow copy ).

Cross-file private status

Splitting a module into several files has a serious defect. Each file has its own private State and has no permission to access the private State of other files. This can be fixed. The following is an example of loosely coupled expansion. Different extended files are kept private:

  1. Var MODULE = (function (my ){
  2. Var _ private = my. _ private = my. _ private | | {},
  3. _ Seal = my. _ seal = my. _ seal | function (){
  4. Delete my. _ private;
  5. Delete my. _ seal;
  6. Delete my. _ unseal;
  7. }, // After the module is loaded, call it to remove the access permission to _ private
  8. _ Unseal = my. _ unseal = my. _ unseal | function (){
  9. My. _ private = _ private;
  10. My. _ seal = _ seal;
  11. My. _ unseal = _ unseal;
  12. }; // Before loading the module, enable access to _ private to expand some of the operations on private content
  13. // Permanent access to _ private, _ seal, and _ unseal
  14. Return my;
  15. } (MODULE | {}));

Copy code

All files can be set in the local Variable _ private, which takes effect immediately for other extensions (that is, all the extended private states are saved in the _ private variable during initialization, and my. _ private output ). The MODULE is fully loaded. The application calls the MODULE. _ seal () method to stop reading private attributes (killing my. _ private output ). If the module needs to be expanded later, a private method is provided. Call the MODULE. _ unseal () method before loading the extended file (restore my. _ private, external restore operation permission ). Load and then call seal ().

This mode has been working with me till now, and I have not seen any other places to do this. I think this mode is useful and worth writing.

Sub-module

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

  1. MODULE. sub = (function (){
  2. Var my = {};
  3. // Multi-level namespace
  4. Return my;
  5. }());

Copy code

Although it is very simple, I 'd like to mention it. The sub-module provides functions of all normal modules, including expansion and private status.

Summary

Most advanced modes can be combined into more useful modes. If I want to propose a design pattern for a complex application, I will combine loose coupling, private status, and sub-modules.

I have not covered performance yet, but I have a small suggestion: the module mode is performance gain. It simplifies a lot and accelerates code downloads. Loose coupling allows parallel downloads without blocking, which is equivalent to improving the download speed. Initialization may be slower than other methods, but it is worth balancing. As long as it is correctly introduced globally, the running performance will not suffer any losses. It may also speed up the loading of sub-modules due to local variables and fewer references.

Finally, an example is provided to dynamically load the sub-module to the parent module (dynamic creation. The private State is no longer needed here. In fact, it is also very easy to add. This Code allows the entire complex code core and its sub-modules to be loaded in parallel completely.

  1. Var UTIL = (function (parent, $ ){
  2. Var my = parent. ajax = parent. ajax || {};
  3. My. get = function (url, params, callback ){
  4. // OK, so I'm cheating a bit
  5. Return $. getJSON (url, params, callback );
  6. };
  7. // Etc...
  8. Return parent;
  9. } (UTIL | {}, jQuery ));

Copy code

I hope you will benefit from it. Please comment and share your thoughts. Now, move on and write better and more modular JavaScript!

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

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.