In-depth understanding of JavaScript series (3) Comprehensive parsing of Module pattern _ javascript skills

Source: Internet
Author: User
The Module mode is a very common mode in JavaScript programming. Generally, everyone knows the basic usage. This article attempts to give you more advanced usage of this mode.
The Module mode is a very common mode in JavaScript programming. Generally, everyone knows the basic usage. This article attempts to give you more advanced usage of this mode.
First, let's take a look at the basic features of the Module mode:
Modular and reusable
Encapsulates the variables and functions. It is not in contact with the global namaspace and is loosely coupled.
Only public methods are exposed. Other private methods are hidden.
The Module mode was first proposed by Eric Miraglia, a yui member four years ago, we will explain the basic usage from a simple example (skip this section if you are familiar with it ).
Basic usage
Let's take a look at the simplest implementation. The Code is as follows:

The Code is as follows:


Var Calculator = function (eq ){
// Private Members can be declared here
Var eqCtl = document. getElementById (eq );
Return {
// Expose public members
Add: function (x, y ){
Var val = x + y;
EqCtl. innerHTML = val;
}
};
};


We can call the following method:

The Code is as follows:


Var calculator = new Calculator ('eq ');
Calculator. add (2, 2 );


You may see that every time you use it, you need to update it. That is to say, each instance is a copy in the memory. If you do not need to transmit parameters or have no special and demanding requirements, we can add a bracket after the last} to achieve self-execution, so that the instance will only have one copy in the memory, but before showing its advantages, let's take a look at the basic usage of this model.
Anonymous Closure
Anonymous closure is the basis for making everything possible, and this is also the best feature of JavaScript. We create a simplest closure function, and the code inside the function remains within the closure, during the entire running cycle, the closure ensures that the internal code is private.

The Code is as follows:


(Function (){
// All variables and functions are declared here, And the scope can only be in this anonymous closure.
//... But the code here can still access external global objects
}());


Note that the brackets behind anonymous functions are required by the JavaScript language, because if you do not declare them, the JavaScript interpreter declares a function by default, with parentheses, that is, creating a function expression, that is, self-execution. It does not need to be in the new format as above. Of course, you can declare it as follows:
(Function () {/* Internal Code */})();
However, we recommend that you use the first method. For more information about function self-execution, I will provide a special article later.
Reference global variables
JavaScript has a feature called implicit global variables. No matter whether a variable has been used or not, the JavaScript interpreter reversely traverses the scope chain to find the var Declaration of the entire variable. If no var is found, the interpreter assumes that the variable is a global variable. If the variable is used for the value assignment operation, if it does not exist before, the interpreter will automatically create it, this means that it is very easy to use or create global variables in anonymous closures, but it is difficult to manage the code. Especially those who read the code are looking at a lot to differentiate which variables are global, which are local ones.
However, in anonymous functions, we can provide a simple alternative. We can pass global variables as a parameter to anonymous functions and then use them. Compared with implicit global variables, it is clear and fast. Let's look at an example:

The Code is as follows:


(Function ($, YAHOO ){
// Here, our code can use the global jQuery object. The same is true for YAHOO.
} (JQuery, YAHOO ));


Currently, many class libraries use this method, such as jQuery source code.
However, sometimes we may not only need to use global variables, but also want to declare global variables. What should we do? We can return this global variable through the return value of the anonymous function, which is a basic Module mode. Let's look at the complete code:

The Code is as follows:


Var blogModule = (function (){
Var my = {}, privateName = "";
Function privateAddTopic (data ){
// Here is the internal processing code
}
My. Name = privateName;
My. AddTopic = function (data ){
PrivateAddTopic (data );
};
Return my;
}());


The above Code declares a global variable blogModule with two accessible attributes: blogModule. addTopic and blogModule. name. In addition, other code remains private in the closure of the anonymous function. At the same time, based on the example of passing in global variables above, we can also easily pass in other global variables.
Advanced usage
The above content is enough for most users, but we can also extend a more powerful and scalable structure based on this mode. Let's look at it one by one.
Extension
One limitation of the Module mode is that all code must be written in one file. However, in some large projects, it is very important to separate a function into multiple files, because it is easy to develop with multiple partners. Let's look back at the global parameter import example above. Can we pass blogModule itself in? The answer is yes. We first pass blogModule in, add a function attribute, and then return the result to achieve what we call. The Code is as follows:

The Code is as follows:


Var blogModule = (function (my ){
My. AddPhoto = function (){
// Add internal code
};
Return my;
} (BlogModule ));


Does this code look like the Extension Method in C? It's a bit similar, but it's actually different. At the same time, although var is not necessary, we use it again to ensure consistency. After the code is executed, AddPhoto under blogModule can be used, at the same time, the code inside the anonymous function still ensures privacy and internal status.
Loosely Coupled Expansion
Although the above Code can be executed, it must first declare blogModule and then execute the above extension code. That is to say, the steps cannot be messy. How can this problem be solved? Let's recall that all variables we declare are as follows:
Var cnblogs = cnblogs || {};
This is to ensure that the cnblogs object is directly used when it exists. If it does not exist, it is directly assigned as {}. Let's take a look at how to use this feature to implement any Loading Order of the Module mode:

The Code is as follows:


Var blogModule = (function (my ){
// Add some features
Return my;
} (BlogModule | | {}));


With this Code, every separately separated file ensures this structure, so we can load it in any order. Therefore, var must be declared at this time, because it is not declared, other files cannot be read.
Tightly coupled Expansion
Although the loosely coupled extension is awesome, there may also be some restrictions. For example, you cannot rewrite some of your attributes or functions, or use the Module attributes during initialization. Tightly coupled expansion limits the Loading Order, but provides an opportunity for us to reload. See the following example:

The Code is as follows:


Var blogModule = (function (my ){
Var oldAddPhotoMethod = my. AddPhoto;
My. AddPhoto = function (){
// Reload the method. You can still use oldAddPhotoMethod to call the old method.
};
Return my;
} (BlogModule ));


In this way, we achieve the purpose of overloading. Of course, if you want to continue using the original attributes internally, you can call oldAddPhotoMethod.
Cloning and inheritance

The Code is as follows:


Var blogModule = (function (old ){
Var my = {},
Key;
For (key in old ){
If (old. hasOwnProperty (key )){
My [key] = old [key];
}
}
Var oldAddPhotoMethod = old. AddPhoto;
My. AddPhoto = function (){
// After cloning, it is overwritten. Of course, you can continue to call oldAddPhotoMethod.
};
Return my;
} (BlogModule ));


This method is flexible and flexible, but it also requires a flexible cost. In fact, the property object or function of this object is not copied at all, but it only references the same object, so if the old object changes it, the attributes or function of the cloned object will also be changed. To solve this problem, we must use recursion, but recursion does not work well in assigning values to function functions, so we eval the corresponding function during recursion. In any case, I still put this method in this post. You just need to pay attention when using it.
Private object sharing across files
Through the above example, we know that if a module is divided into multiple files, each file must have the same structure. That is to say, private objects in each file anonymous function cannot be accessed across objects, what should we do if we have to use it? Let's first look at a piece of code:

The Code is as follows:


Var blogModule = (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;
};
Return my;
} (BlogModule | | {}));


Any file can set the attribute for its local Variable _ private, and the setting takes effect immediately for other files. Once this module is loaded, the application will call blogModule. _ seal () "Lock", which will prevent external access to the internal _ private. If this module needs to grow again, any file within the application's lifecycle can call _ unseal () "unlock" and then load the new file. Call _ seal () "Lock" again after loading ".
Sub-module
The last and simplest way to use it is to create a sub-module.

The Code is as follows:


BlogModule. CommentSubModule = (function (){
Var my = {};
//...
Return my;
}());


Although it is very simple, I still put it in, because I want to explain that sub-modules also have all the advanced usage methods of General modules, that is to say, you can use some of the above application methods for any sub-module again.
Summary
Most of the above methods can be used in combination. Generally, if you want to design a system, you may use loosely coupled expansion, private State, and sub-module. In addition, I did not mention performance issues here, but I think the Module mode is highly efficient, with less code and fast loading. The loosely coupled extension allows parallel loading, which improves the download speed. However, the initialization time may be slower, but it is worthwhile to use a good mode.
References:
Http://yuiblog.com/blog/2007/06/12/module-pattern/
Http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
Synchronization and recommendation
This article has been synchronized to the Directory Index: a deep understanding of the JavaScript Series
I have a deep understanding of the JavaScript series of articles, including original articles, translations, reposts, and other types of articles. If they are useful to you, I suggest you support them and give uncle the motivation to write.

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.