It's private, because nothing outside the object that is created by the immediate execution of the anonymous function whose definition starts on line 1 can access the variable counter.
It's not really static, because, if Gadget is defined in an inner scope, the storage used for Counter could be garbage-collected once Gadget and all of the Gadget objects that it has created have been discarded. But it behaves like static for most purposes when used at the top level.
Confusingly, this code in the more complete example that follows does not do what Stefanov says.
var Gadget = (function () {
var counter = 0, NewGadget;
NewGadget = function () {
counter += 1;
};
NewGadget.prototype.getLastId = function () {
return counter;
};
return NewGadget;
}()); // execute immediately
var iphone = new Gadget();
iphone.getLastId(); // 1
var ipod = new Gadget();
ipod.getLastId(); // 2
var ipad = new Gadget();
ipad.getLastId(); // 3
He writes: "Because we’re incrementing the counter with one for every object, this static property becomes an ID that uniquely identifies each object created with the Gadget constructor.". That's just wrong. There is only one counter
, and all of the Gadget objects have a reference to it. The function getLastId()
does just what its name suggests: gets the most recently issued id, and not the value of counter when the gadget was created.
So, the above example runs, and produces the results indicated by the comments. But if you try
iphone.getLastId(); // 3
one more time, you get 3
— the current value of counter, not the value when iPhone
was created.
To get the effect of each Gadget having a unique id, we can use a fresh variable for each Gadget, like this:
var Gadget = (function () {
var counter = 0, NewGadget;
NewGadget = function () {
counter += 1;
var myId = counter;
this.myUid = function () {
return myId;
};
};
return NewGadget;
}()); // execute immediately
var iphone = new Gadget();
iphone.myUid(); // 1
var ipod = new Gadget();
ipod.myUid(); // 2
var ipad = new Gadget();
ipad.myUid(); // 3
iphone.myUid(); // 1
Note that myId
is definitely not static, even though we are using the same pattern as for counter
. However, it is private. There is a separate myId
for each Gadget, and it's not a property of the Gadget object — it's truly hidden. But the object's myUid
function has closed over it.