Вопрос

I'm moving through the "Learning Javascript Design Patterns" book and I came across a peculiarity I can't quite wrap my head around. Looking at the following snippet:

var myNamespace = (function () {

  var myPrivateVar, myPrivateMethod;

  // A private counter variable
  myPrivateVar = 0;

  // A private function which logs any arguments
  myPrivateMethod = function( foo ) {
      console.log( foo );
  };

  return {

    // A public variable
    myPublicVar: "foo",

    // A public function utilizing privates
    myPublicFunction: function( bar ) {

      // Increment our private counter
      myPrivateVar++;

      // Call our private method using bar
      myPrivateMethod( bar );

    }
  };

})();

I get what's going on generally in the code. But I don't understand two excess pairs of parenthesis, the first being the pair that wraps function, and the second empty pair right before the empty semicolon. I would expect the formatting to look more like this:

var myNamespace = function () {

  var myPrivateVar, myPrivateMethod;

  // A private counter variable
  myPrivateVar = 0;

  // A private function which logs any arguments
  myPrivateMethod = function( foo ) {
      console.log( foo );
  };

  return {

    // A public variable
    myPublicVar: "foo",

    // A public function utilizing privates
    myPublicFunction: function( bar ) {

      // Increment our private counter
      myPrivateVar++;

      // Call our private method using bar
      myPrivateMethod( bar );

    }
  };

};

Needless to say, I tried compiling the code the way I thought it should look and it returned errors. Can anyone point me toward an explanation of why this works the way it does?

Это было полезно?

Решение

Sure. We can simplify the example so that the reason is obvious:

This assigns a function to a variable:

var func=function(){
  return 10;
}

This assigns the result of the function to another variable:

var value=func();

Now we'd like to call a function without having to name it, so we combine the above lines:

var value=function(){
  return 10;
}();

But wait, this looks too much like defining a function - especially if the body is so long that we don't see the pair of parenthesis in the end. We want to indicate that we are calling a nameless function, so conventionally we write it like this:

var value= (function(){
  return 10;
})();

Replace the part in the brackets with "func", and you'll see what I mean.

Другие советы

The important thing to understand is the last set of parenthesis () . This invokes the function that it created. This is called a self invoking function. So to break down the code you have.

  1. Variable Namespace is declared.
  2. function is then created
  3. That function is then invoked
  4. The object in the return statement is then returned
  5. Namespace is then set to the value of the returned object

You could leave off the parenthesis around (function) and it would run just fine. The important part is the () at the end.

Think of it as setting a variable to the object the function returns.

It's quite simple. The reason for this is that, when you make a variable using var, it has a limited scope to the next containing block. A function counts as a containing block. So, if a variable is declared inside of this function, there will be no chance of it messing up any variables in the global scope. But, setting the namespace variable to the function itself is very, very useless. The () means Hey, execute this function.

You probably wouldn't be surprised to see this:

var something=function(){/*some random stuff*/};
something();

and the way things are done here just bypasses that and executes the function directly, and sets the namespace variable to the returned object.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top