Reputation: 549
var namepace = (function () {
var loca = 5;
var getLocal = function () {
loca += 1;
return loca;
};
return {
glob: getLocal,
blog: loca,
frog: function () {
return loca;
}
};
})();
alert(namepace.glob());
alert(namepace.blog);
alert(namepace.frog());
My question is why does the function alert(namepace.blog);
return 5
rather than 6
as I would expect?
Upvotes: 8
Views: 285
Reputation: 11174
It helps to think of the execution context when a JavaScript program is run. JavaScript evaluates references (not values directly).
The global context consists of global variables and objects. In this case it is (at the time the JavaScript interpreter reads the namespace instruction):
namespace = {f} // namespace references a function
This means namespace is referencing a function. At the first alert the following execution context for namespace is created:
loca = 5 // loca references the value 5
getLocal = {f} // getLocal references a function
return { // return object with glob, blog and frog as properties
glob = { getLocal() } // references the function getLocal()
blog = 5 // blog references same value as loca: 5
frog = {f} // references anonymous function
}
Consequently the function glob is called. glob references a function named getLocal. glob's execution context is as follows:
loca = 6 // loca now references the value 6
return loca // return value referenced by loca
The next call is blog and this one returns the value 5. It does not reference loca. It merely references the value that loca had when creating the execution context. At the time the execution context was created loca referenced a value of 5, and thus blog references the value of 5. No matter how often you call glob, blog will still reference the value of 5.
In the last alert statement frog is invoked. frog references an anonymous function that is now executed. frog's execution context is as follows
return loca // Go and get the value that is referenced by loca
That's basically it. Try to think "reference to a value" whenever you think value. This can help to get used to it. And try to visualize the execution contexts when a program is run (like being a human debugger).
Upvotes: 1
Reputation: 239623
Important thing to understand here is, all the names in JavaScript are references to other objects.
When you create an Object with Object literal, the left hand side names are used to refer the objects already referred by the right hand side names.
In this case, when you do
blog: loca,
you are saying blog
to refer the value referred by loca
, which is 5. Later on when you increment loca
, it becomes 6
, it means it refers to some other value, but blog
still refers to the value 5
.
That is why you are getting 5
.
But when you do
namepace.frog()
you are getting the current value referred by loca
. Since it is assigned 6
in getLocal
, you are getting 6
.
Incrementation creates new number object
To make it even more clear, when you do
loca += 1;
or
loca++;
what internally happens is, something like this
oldValue = loca
newValue = oldValue + 1
loca = newValue
Reference from ECMAScript 5.1 Specification, for +=
and for ++
Since numbers are immutable objects (can you change the value of 5
? You cannot, that is why it is called an immutable object), a new number object is created with one added to it and the name loca
is made to refer the new object.
Mutable Objects
If you think about mutable objects,
var namepace = (function () {
var loca = [];
return {
glob: function () {
loca.push(1);
return loca;
},
blog: loca,
frog: function () {
return loca;
}
};
})();
console.log(namepace.glob());
// [ 1 ]
console.log(namepace.blog);
// [ 1 ]
console.log(namepace.frog());
// [ 1 ]
Now, both blog
and loca
refer the same array object. What happens in glob
is called mutating. You are just adding one element to the array object referred with two names blog
and loca
. That is why namepace.blog
also prints [ 1 ]
.
Upvotes: 6
Reputation: 124
When assigning to namespace.blog
, you are using pass-by-value to the setter. This means that there is no reference back to loca
.
When you access the value through namespace.frog
, you are using the original variable, which is leveraging JavaScript's closure scoping to resolve to loca
, the next available definition up the local scope chain.
You can read up on scoping here: What is the scope of variables in JavaScript?
Upvotes: 0
Reputation: 78
its a logic problem. when function take some time. in that time variable assigned.. look below code. and try this
var namepace = (function () {
var loca = 5;
var getLocal = function () {
loca += 1;
return loca;
};
console.log(loca);
return {
glob: getLocal,
blog: loca,
frog: function () {
return loca;
}
};
})();
alert(namepace.glob());
alert(namepace.blog);
alert(namepace.frog());
Upvotes: 1