简体   繁体   中英

How does defining and immediately calling an anonymous function solve namespace problems?

I'm reading this page where it says:

 myNameSpace = function(){ var current = null; function init(){...} function change(){...} function verify(){...} return{ init:init, change:change } }(); 

Instead of returning the properties and methods I just return pointers to them. This makes it easy to call functions and access variables from other places without having to go through the myNameSpace name.

But I don't see how that's true. You still have to do myNameSpace.init() to call init . init() alone doesn't work.

Edit: it occurred to me later that maybe the author meant they were able to call init() without qualification inside the anonymous function . But what stumped me is that the author's previous examples were already able to do that. Specifically, in the immediately foregoing example:

myNameSpace = function(){
  var current = null;
  function verify(){...}
  return{
    init:function(){...}
    change:function(){...}
  }
}();

s/he defined init as s/he was returning it, instead of the example above where s/he defined init first then returned a pointer to it. But in that earlier example, within the anonymous function, if you wanted to call init() without having to do myNameSpace.init() , you already can. So how is the quoted example better?.

Can someone explain? Thanks.

The idea of using a function to clean up scope is, let's say you have a program that looks like this:

var number = 10;
var multiplier = 2;
var endingText = " days left!";
var string = (10 * 2) + endingText;
// string is "20 days left!"

This is an extremely contrived example, but hopefully it's obvious enough that this will declare four variables in the global scope, which is horrible. Let's say what you really want is string , but you still want to keep the other three variables around for whatever reason. You can put them inside an anonymous function, like so:

var string;
(function(){
  var number = 10;
  var multiplier = 2;
  var endingText = " days left!";
  string = (10 * 2) + endingText;
})();
// string is still "20 days left!"

Because variables are function scoped, number , multiplier and endingText are NOT declared in the global scope. However, you are still able to use them to get the result that you wanted in the first place.

By the way, you need to wrap parens around a function if you want to immediately invoke it. Also, you should not confuse this with namespacing. Namespacing in JavaScript is the idea of assigning meaningful values to the properties of objects.

var foo = {
  hello: "goodbye",
  frank: "bob"
};

hello and frank are declared in the foo namespace. That's all there is to it. The example that you posted uses both the namespacing concept and immediately invoking function concept to clean up variables.

The wording is a bit confusing. He meant to say:

Functions and variables can now be easily accessed without a namespace from inside the module

- in contrast to the object literal pattern or the previous example where he put the public methods directly on the exported object. Of course, from outside you always will need to access them as properties of the namespace object - that's the whole point of making it a namespace :-)

For an example, let's fill the functions with a some minimal code:

myNameSpace = function(){
  var current = null;
  function verify(…){…}
  return {
    init:function(el){
      el.addEventListener("input", myNameSpace.change, false);
      //                           ^^^^^^^^^^^^^^^^^^
    },
    change:function(){
      if (!verify(this.value)) alert("wrong");
    }
  }
}();
myNameSpace.init(document.getElementById("testInput"));

vs

myNameSpace = function(){
  var current = null;
  function verify(…){…}
  function change(){
    if (!verify(this.value)) alert("wrong");
  }
  function init(el){
    el.addEventListener("input", change, false);
    //                           ^^^^^^
  }
  return {
    init:init,
    change:change
  }
}();
myNameSpace.init(document.getElementById("testInput")); // no difference here

The differences may be minimal in this example, but when you have lots of functions mutually referencing each other it can matter. Also, you would know that all local, namespace-less functions belong to the current module, which massively increases maintainability when dealing with many different namespaces.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM