Russ
Russ

Reputation: 549

Javascript variable scope and value

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

Answers (4)

Ely
Ely

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

thefourtheye
thefourtheye

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

Trey Cordova
Trey Cordova

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

Venkatesh TR
Venkatesh TR

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

Related Questions