Namespaces in JavaScript

Source: Internet
Author: User

Global variables should be retained by objects that have system-wide dependencies, and their naming should avoid ambiguity and minimize the risk of naming conflicts.
In practice, this means that you should avoid creating global objects unless they are absolutely necessary.

So what do you do about it? The traditional approach tells us that the best way to eliminate global policy is to create a few global objects that are the actual namespaces of potential modules and subsystems.
I'll explore several ways about namespaces and end with an elegant, secure, and flexible solution I got based on a recent article by James Edwards.

Statically named spaces
I use static namespaces as the covering terminology for solutions that are actually hardcoded for those namespace tags. Yes, you can reassign one namespace to another,
However, the new namespace will refer to the same object as the old one.

1. By direct distribution
The most basic method. It's very verbose, and if you want to rename these namespaces, you have a job to do. But it is safe and clearly understood.

var myApp =0= function () {    return myapp.id++;   = function () {    0;    && Console.log (    myapp.next (),    myapp.next (),    myapp.reset (),    // 0, 1, undefined, 0

You can also use this to refer to sibling attributes to make future maintenance easier, but this is a little risky because there is nothing to prevent your methods in those namespaces from being reassigned.

  {}myapp.id  = 0  ;myapp.next  = function () { Span style= "color: #0000ff;"   >return   = function () { this .    id = 0  ; }myapp.next ();  // 0  myapp.next (); // 1  var  getnextid = Myapp.next;getnextid ();  // nan whoops!  

2. Use object literals
Now we just need to reference the namespace name once, so it's easier to change the name later (assuming you haven't repeatedly referenced the namespace).
There is still a danger that the value of this may throw a "surprise" – however, it is assumed that objects defined in the literal structure of an object will not be redistributed relatively securely.

var myApp = {    0,    next:function () {        returnthis. id++;       },    reset:function () {        this0;         && Console.log (    myapp.next (),    myapp.next (),    myapp.reset (),    // 0, 1, undefined, 0

3. Module Mode
I found myself more recently using module mode. Logic is separated from the global domain by a method wrapper (usually self-invoking), which returns an object that represents the interface that the module exposes.
by calling this method immediately and assigning the result to a namespace variable, we lock the API of the module in the named variable.
In addition, any variables that are not included in the return value will always remain private and visible only to the public method that references them.

 var  myApp = (function () { var  id= ;  return   {next:function () {
    return  id++;              }, Reset:function () {id  = 0  ;  }    };   })(); Window.console  && Console.log (Myapp.next (), Myapp.next (), Myapp.res ET (), Myapp.next ())  // 0, 1, Undefined, 0< /span> 

As with the object literal example, the namespace name can be easily replaced, but there are additional advantages: The object literal is class four – it's all about attribute assignment,
There is no space to support logic. In addition, all properties must be initialized, and property values cannot be easily referenced across objects (so, for example, internal closures are not possible).
The module mode does not have any of the above constraints and gives us additional privacy benefits.

Dynamic namespaces
We can also refer to this section as namespace injection. Namespaces are represented by a direct reference method wrapper inside the proxy – which means that we no longer need to package the return value assigned to the namespace.
This makes the namespace definition more flexible and lets you have separate instances of multiple modules that exist in a separate namespace (or even in the global context).
Dynamic namespaces support the full features of the module pattern and attach the advantages of being intuitive and readable.

4. Provide namespace parameters
Here we just pass the namespace as a parameter to the self-invoking method. The variable ID is private because he is not assigned to the context.

var myApp = {};(function (context) {     var0;     = function () {        return id++;        };     = function () {        0;         }}) (MYAPP);   && Console.log (    myapp.next (),    myapp.next (),    myapp.reset (),    // 0, 1, undefined, 0

We can even set the context to the global object (through a word change!). )。 This is a huge asset for the library owners – they can wrap their features in a self-calling function,
Then let the user decide if they are global (John Resig was an early adopter of the theory when he wrote JQuery).

  {};(function (context) { var  id = 0      = function () { return Id++;    }; Context.reset  = function () {id  = 0 this  ); Window.console  && Console.log (next (), Next (), Reset (), Next ()) /span>// 0, 1, undefined, 0  

5. Use this as the namespace proxy
James Edwads recently published an article that aroused my interest. "My favorite JavaScript Design Patter" is clearly misunderstood by many commentators, and
they think he may also be using the module model. This article promotes a variety of techniques (which can lead to confusion for readers),
but at its core is a bit of a genius that I have modified and rendered as a namespace tool. The beauty of the
pattern is that it is used only in the way that the language is designed-not much, not speculative, or trickery.
also because the namespace is injected through the This keyword, which is immutable in a given execution context, it cannot be accidentally modified.

  {};(function () { var  id = 0  ;   function () { return  id++;    };  this . Reset = function () {id  = 
   
    0  
    ;    }}). apply (MYAPP); Window.console  &&
     Console.log (Myapp.next (), Myapp.next (), Myapp.res ET (), myapp.next ());  
    // 
    0, 1, undefined, 0  
   

Even better, the apply (and call) API provides natural isolation from the context and parameters – so it is very clean to pass additional parameters to the module creator.
The following example shows this and shows how to run a module independently of multiple namespaces.

varSubsys1 = {}, Subsys2 = {};varNextidmod =function (startid) {varid = Startid | |0;  This. Next =function () {returnid++;    };  This. reset =function () {ID=0;    }};nextidmod.call (SUBSYS1); Nextidmod.call (Subsys2, +); Window.console&&Console.log (Subsys1.next (), Subsys1.next (), Subsys2.next (), Subsys1.reset (), Subsys2.next (), Subsy S1.next ())//0, 1, undefined, 1001, 0

Of course if we need a global ID generator, it's very simple ...

nextidmod ();     && Console.log (    next (),    next (),    Reset (),    //0, 1, undefined, 0

The ID Generator tool we use as an example does not show the full potential of this pattern. By wrapping an entire library and using the This keyword as the alias for the namespace,
We make it easy for users to run this library in any context they choose (including the global context).

// Library Code var protoquerymoojo = function () {      //everything}/ /user codevar thirdparty = {};p rotoquerymoojo.apply (thirdparty);

Other considerations
I want to avoid namespace nesting. They're hard to track (both for people and computers) and they make your code a lot more of a mess.
As Peter Michaux points out, deep nested namespaces may be the legacy of old-fashioned Java developers who re-create their familiar and loving long-bag chains.

It is also possible to pin a separate namespace through a. js file (although only through namespace injection or direct allocation of each variable), you should be cautious about dependencies.
Also, binding namespaces to files can help readers understand the entire code more easily.

Because JavaScript does not have a formal namespace structure, there are many natural ways of forming it.
This survey explains only a few of them, and there may be better techniques I didn't find. I'd love to know about them.

Namespaces in JavaScript

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.