0

I am trying to learn the best practices of creating objects and object instances. One way I understood of doing this was by using a closure to return an object all wrapped up as an IIF:

myApp2 = (function() {
  var count = 1;
  return {
    getCount: function(){return count},
    incCount: function(){count++}
  };
}())

var test = myApp2
console.log(test.getCount()); // outputs 1
console.log(test.incCount()); // increment count by 1
console.log(test.getCount()); // outputs 2
var test2 = myApp2            // I thought this would create new context
console.log(test2.getCount());// outputs 2, not 1 as expected

Please correct my understanding..

timebandit
  • 794
  • 2
  • 11
  • 26
  • ["IIFE"](http://benalman.com/news/2010/11/immediately-invoked-function-expression/), not "IIF" – zzzzBov Mar 24 '15 at 18:41
  • How do you distinguish between "objects" and "object instances"? – Bergi Mar 24 '15 at 18:41
  • 1
    Object assignment is always by reference - `myApp2 == test` and `test == test2`. You'll have to invoke the function again to create a new closure context. – Bergi Mar 24 '15 at 18:42
  • @Bergi i'm still learning, coming from a python background i want to be able to create a unique copy of a structure(data+methods) that already exists. – timebandit Mar 24 '15 at 22:35
  • @ImranNazir: That's not really possible in javascript, given that a structure (and especially its methods) might have some internal state (like `count` in your example) that is not accessible from outside, and can't be cloned without the structure explicitly supporting that. I guess it's pretty similar in python, only that you have way less internal state there (no closures) – Bergi Mar 24 '15 at 23:01
  • @Bergi well Python supports class but according to Crockford Javascripts attempt is a cluncky way to keep people from c++/Python etc happy. He recommends using **Object.create** or using closures so I am tying to get my head around them both, to try and understand them inside out. Python doesn't over complicated things as much as ECMAScript seems to do. – timebandit Mar 24 '15 at 23:06

2 Answers2

1

If you want to have different objects, you can use a function instead of an IIFE, and call it once for each object:

function myApp2 () {
  var count = 1;
  return {
    getCount: function(){return count},
    incCount: function(){count++}
  };
}
var test = myApp2();
console.log(test.getCount()); // outputs 1
console.log(test.incCount()); // increment count by 1
console.log(test.getCount()); // outputs 2
var test2 = myApp2();         // creates new object
console.log(test2.getCount());// outputs 1
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Ok i think I see it. The IIFE is run once when the script is run and returns an object forming a closure. So **test** & **test2** are pointing to the same object. By removing the IIFE **myApp2** is really being invoked twice. But is what I have done really a closure? Is it a function within a function? – timebandit Mar 24 '15 at 22:47
  • Yes, it's a closure. You may be interested in [How do JavaScript closures work?](http://stackoverflow.com/q/111102/1529630). – Oriol Mar 24 '15 at 23:26
1

Well if you take a look at the definition of myApp2 you see it is the result of a function call. So you are simply creating another reference test2 pointing to the same object that myApp2 points to, the same as with test. So invoking functions on test2 is the same as invoking functions on test because both refer to the same object.

user268396
  • 11,576
  • 2
  • 31
  • 26
  • I was going on what I understood in that a new closure would be created on each call. – timebandit Mar 24 '15 at 22:40
  • There is only *one* such call. Right where the anonymous function is defined, it is also immediately invoked. So the result assigned to `myApp2` is that of this one function call. – user268396 Mar 24 '15 at 23:44