JavaScript namespace mode

Source: Internet
Author: User
Tags define function

Objective

A namespace can be considered a logical grouping of code under a unique identifier. Why does the concept of namespaces appear? Because the number of words available is too small, and different people write programs can not all variables are not the same name phenomenon. In JavaScript, namespaces can help prevent conflicts with other objects or variables under the global namespace. namespaces also help organize your code, with greater maintainability and readability. The purpose of this article is to explore several common namespace patterns in JavaScript, providing us with a way of thinking.

The JavaScript execution environment has many unique features, and the use of global variables and functions is one of them. JavaScript's execution environment is made up of a variety of global variables, which are created before the function execution environment. These global variables are mounted under global objects, and in the browser, the window object is equal to the global object. Then, any variables and functions declared in the global scope are properties of the Window object, and when there is a conflict in the name, there are some problems that are not controllable. Global variables can cause the following problems:

    • Naming conflicts
    • The fragility of the code
    • Difficult to test

A reasonable use of namespaces in programming development avoids collisions of the same variables or object names. Also, namespaces help organize your code, which is more maintainable and readable. Although there is no native namespace support available in JavaScript, we can use other methods (objects and closures) to achieve similar effects. Here are some common namespace patterns:

1. Single global variable

A popular namespace pattern in JavaScript is to select a global variable as the primary reference object. Because each possible global variable becomes a property of a unique global variable and no more global variables are created, conflicts with other claims are avoided.

The single global variable pattern is already in use in a number of JavaScript class libraries, such as:

    • Yui defines the only Yui global object
    • jquery defines $ and jquery,$ used by other class libraries when using jquery
    • Dojo defines a dojo global variable
    • The Closure class library defines a Goog global object
    • The underscore class library defines a _ global object

Examples are as follows:

1 var MyApplication = (function () {2     function () {3         //***4     },5     return {6         //**7     }8}) ();

While a single global variable pattern is appropriate for some situations, the biggest challenge is to ensure that a single global variable is unique in the page and that no naming conflicts occur.

2. Namespace prefixes

namespace prefix pattern It is very clear that you choose a unique namespace, and then declare variables, methods, and objects behind it. Examples are as follows:

1 var = Myapplication_propertya = {};2 var = myapplication_propertya = {};3 4 function Myapplication_mymethod () {5     /// 6}

In a way, it does reduce the probability of a naming conflict, but it does not reduce the number of global variables. When an application is scaled up, it produces many global variables. Within the global namespace, this pattern is strongly dependent on the prefix that no one else is using, and it is sometimes difficult to determine whether someone has used a particular prefix, and it is important to pay special attention when using this pattern.

3. Object literal notation

The object literal pattern can be thought of as an object that contains a set of key-value pairs, with each pair of keys and values separated by colons, or a new namespace for the code. Examples are as follows:

1 var myapplication = {2      3     //can easily define function for object literal 4     getinfo:function () {5         //* * * 6     }, 7      8     //CAN Further support Object namespace 9     models:{},10     views:{11         pages:{}12     },13     collections:{}14};

As with adding properties to an object, we can also add properties directly to the namespace. The object literal method does not pollute the global namespace and logically assists in organizing code and parameters. Moreover, the readability and maintainability of this method is very strong, of course, we should use the same name as the existence of variables to test, so as to avoid conflicts. Here are some common detection methods:

1 var myapplication = MyApplication | | {}; 2  3 if (!myapplication) {4     MyApplication  = {}; 5} 6  7 Window.myapplication | | (Window.myapplication | | {}); 8  9//For jQuery10 var myapplication = $.fn.myapplication = function () {};11 var myapplication = MyApplication = = = U Ndefined? {}: MyApplication;

The object literal provides us with an elegant key/value syntax that allows us to organize the code very easily, encapsulating different logic or functionality, and is extremely readable, maintainable, and extensible.

4. Nesting namespaces

The nested namespace pattern can be said to be an upgraded version of the object literal pattern, which is also an effective way to avoid conflicts, because even if a namespace exists, it is unlikely to have the same nested object. Examples are as follows:

1 var myapplication = MyApplication | | {};2 3//define nested objects 4 Myapplication.routers = Myapplication.routers | | {};5 myApplication.routers.test = MyApplication.routers.test | | {};

Of course, we can also choose to declare a new nested namespace or property as an indexed property, such as:

myapplication[' routers ' = myapplication[' routers '] | | {};

Using nested namespace patterns makes code easy to read and organized, and relatively secure and less prone to conflict. The downside is that if our namespaces are nested too much, we increase the query effort of our browsers, and we can reduce the query time by locally caching sub-objects that we want to access multiple times.

5. Function expressions that are called immediately

The immediate call function (Iife) is actually an anonymous function that is called immediately after it is defined. In JavaScript, function calls provide a convenient way to implement private variables and methods because variables and functions are explicitly defined in such a context that can only be accessed internally. Iife is a common method for encapsulating application logic to protect it from the global namespace, which can also play a special role in namespaces. Examples are as follows:

1///namespace and undefined as parameter passing, make sure: 2//1. Namespaces can be modified locally, without overriding the function external context 3//2.undefined parameter value is to ensure undefined, avoid undefined 4 defined in ES5 specification (fun Ction (namespace, undefined) {5  6     //Private attribute 7     var foo = "Foo"; 8         bar = "Bar"; 9     //Public methods and properties     Nam Espace.foobar = "Foobar";     Namespace.sayhello = function () {         say ("Hello world!");     };15     //Private Method-     function Say (str) {         Console.log ("you said:" + str),     };20}) ( Window.namespace = Window.namespace | | {});

Extensibility is the key to any scalable namespace pattern, which can be easily achieved with iife, and we can use Iife again to add more functionality to the namespace.

6. Namespace Injection

Namespace injection is another variant of iife, which "injects" methods and properties into a specific namespace from within the function wrapper, using this as the namespace proxy. The advantage of this pattern is that functional behavior can be applied to multiple objects or namespaces. Examples are as follows:

1 var myapplication = MyApplication | | {}; 2 myapplication.utils = {}; 3  4 (function () {5     var value = 5; 6      7     this.getvalue = function () {8         return value; 9     }10 11
   
    //defines a new sub-namespace of     This.tools = {};13}). Apply (myapplication.utils); (function () {     this.diagnose = function () {         "diagnose";     }19}). Apply (MyApplication.utils.tools), 20 21//the same way on the normal iife to expand the function, Simply pass the context as a parameter and modify it instead of just using this
   

There is also a way to use the API to achieve a natural separation of context and parameters, which feels more like the creator of a module, but as a module, it also provides an encapsulation solution. Examples are as follows:

1 var ns = NS | | {}, 2     ns1 = ns1 | | {}; 3  4//module, namespace creator 5 var creator = function (val) {6     var val = val | | 0; 7  8     this.next = function () {9
   return val + +,     };11     this.reset = function () {         val = 0;14}15}16 +     creator.call (NS); Next, Ns.reset already exists at this time (ns1, creator.call);//ns1 contains the same method, but the value is rewritten to 5000

Namespace injection is used to specify a similar feature base set for multiple modules or namespaces, but it is best to use it when declaring a private variable or method, and other times the use of nested namespaces is sufficient.

7. Automatic nesting of namespaces

Nested namespace patterns provide an organized hierarchical hierarchy of code units, but each time you create a hierarchy, we also have to ensure that it has a corresponding parent level. When the number of levels is large, it can bring us a lot of trouble, we can not quickly and easily create the level you want to create. So how do we solve this problem? Stoyan Stefanov proposes to create a method that receives a string parameter as a nested, parses it, and automatically populates the base namespace with the desired object. Here is an implementation of this pattern:

1 function Extend (ns, nsstr) {2     var parts = Nsstr.split ("."), 3         parent = NS, 4         PL; 5  6     PL = Parts.len Gth 7  8     for (var i = 0; i < pl; i++) {9         //attribute if not present, create it if         (typeof parent[parts[i]] = = = "undefined") {11             Parent[prats[i]] = {};12         }         parent = parent[parts[i]];14     }15     return parent;16}17 18//usage var myapplication = MyApplication | | {};20 var mod = Extend (MyApplication, "module.module2");

Previously we had to explicitly declare various nested objects for their namespaces, and now they are implemented in a more concise and elegant way.

This article is a general discussion of the namespace patterns commonly used in several JavaScript. In general, there is no big unified, universal solution, only the appropriate solution, the specific choice of which mode depends on the project needs.

JavaScript namespace mode

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.