views:

64

answers:

3

I think I have this figured out, but am hoping to cleary have this explained -- what precisely is the difference between these two javascript snippets?

;Person1 = (function() {
  var FirstName = 'Hello';
  var LastName = 'World';
  this.sayHello = function() {
    alert(FirstName + ' ' + LastName);
  };
});

;Person2 = (function() {
  var FirstName = 'Hello';
  var LastName = 'World';
  this.sayHello = function() {
    alert(FirstName + ' ' + LastName);
  };
})();

One is being executed with the (); at the end, the other is not. They both perform as expected when I do new Person1().sayHello() or new Person2().sayHello(); -- is it what they leave behind? From what I understand, the latter is a closure that is executed AS IT IS READ by the browser, but I haven't yet fully grasped the implications of that. Thanks for your help!

UPDATE: I mistakenly left out the return keyword in the Person2 closure. I did not fix this, however, because the answers were very helpful in describing the implications of doing this :)

A: 

Person1 is a fairly standard type of object constructor function, meant to be called with new. new Person1() creates a new object, and creates a sayHello method on that object.

Person2 is being executed immediately, which is causing some problems! As Person2 is being evaluated, the function is called (in a global context). Inside the execution of that function, this will be the window object. The executed function doesn't return anything, so Person2 ends up being undefined:

>>> Person2 = (function() { var FirstName = 'Hello' // ...}; })(); 
>>> console.log(window.sayHello, Person2);
function() undefined

A new Person2() is resulting in a TypeError "Person2 is not a constructor" for me. If you change this up a little, you can make the Person2 closure return an object with your function:

;Person2 = (function() {
  var FirstName = 'Hello';
  var LastName = 'World';
  return {
    sayHello: function() {
      alert(FirstName + ' ' + LastName);
    }
  };
})();

Person2.sayHello();

Or make it return a function (so you can new Person2()):

;Person2 = (function() {
  var FirstName = 'Hello';
  var LastName = 'World';
  return function() {
    this.sayHello = function() {
      alert(FirstName + ' ' + LastName);
    };
  };
})();
gnarf
Thank you very much for the thoughtful explanation -- I mistakenly left off my return in the creation of the Person2 closure. I'm glad I did, though, because your response reminded me of the `global` implications of doing this.
TimDog
A: 

the first one defines a function inline and Person1 holds a reference to it.

the second one amounts to no action taken. you're defining a function inline and executing it immediately. since the function doesn't return anything, Person2 is undefined.

neither example behaves as you describe, so perhaps you've made an error typing up your example?

lincolnk
`Person2` may be undefined, but it also sets `this.sayHello` which will create `sayHello` on the `window` object.
gnarf
My bad -- you're right, there is a typo in my person3. I've edited it now. Thanks.
TimDog
A: 

The main motivation behind self-invoking functions is to avoid polluting the global namespace. You may be interested in checking out the following resources for further reading:

Daniel Vassallo
Thank you sir. Succinct answer to what I wanted to know: it's all about scope.
TimDog