codemonkey codemonkey - 5 months ago 8
Javascript Question

javascript scope reference variable

so a quesiton I had for a js interview was basically involving scope and variables in an inner function for example supposed you had this:

function(){
var a=b=3;
}


obviously, b is not defined so it has become a global variable, now what happens when you change b in the global scope, does the value of a change also?

I'm not sure how to test this, but for example, if you changed b to 10, would a also now be 10 or would it remain 3?

Answer

obviously, b is not defined so it has become a global variable

Only in loose mode. Don't use loose mode. :-) Use strict mode, where it will be the error it always should have been.

now what happens when you change b in the global scope, does the value of a change also?

No, there is no link between a and b at all. Variables contain values (more on this below). When you do a = b, the value in b is copied to a. No link between the two variables is created.

I'm not sure how to test this

Since we're in loose mode, we know that a raw function call will set this to refer to the global object during the call. Since the implicit b global will be a property of the global object, we can check it by changing this.b (the global):

function foo() {
  var a = b = 3;
  console.log("(Before) a is " + a + ", b is " + b);
  this.b = 10;
  console.log("(After) a is " + a + ", b is " + b);
}
foo();

On browsers we could use window instead of this above, as window is a default global on browsers that refers to the global object.


In a comment you asked about "reference variables." There are no "reference variables" in JavaScript. You're probably thinking about object references. Key fact coming up: It makes no difference to what we're talking about (whether changing b will change a) whether the variable contains an object reference or a primitive. People will tell you it does, but they're confused.

Variables contain values. When you assign an object reference to a variable, that object reference is a value that tells the javaScript engine where the object is in memory. For instance:

var b = {answer:42};

In memory, we have:

                 +------------+
[b:REF55134]-----|  (object)  |
                 +------------+
                 | answer: 42 |
                 +------------+

The value in b is a reference to the object. I've represented it above as REF55134, but we can never actually access the raw value of that reference. That raw value doesn't matter, it's just a thing (akin to a number) that tells the JavaScript engine where the object is.

Now if we do this:

var a = b;

...we copy the value of b into a, and get this in memory:


[b:REF55134]--+
              |   +------------+
              +-->|  (object)  |
              |   +------------+
[a:REF55134]--+   | answer: 42 |
                  +------------+

a and b have the same value in them, and so they both point to the same object.

Changing b will still have no effect at all on a. Where people get confused is that if we change the state of the object b points to, naturally we can see that changed state through a as well. The value in b didn't change, the state of the thing it's pointing to changed.

E.g.:

b.question = "Life, the Universe, and Everything";

Gives us:


[b:REF55134]--+
              |   +------------------------------------------------+
              +-->|                   (object)                     |
              |   +------------------------------------------------+
[a:REF55134]--+   | answer: 42                                     |
                  | question: "Life, the Universe, and Everything" |
                  +------------------------------------------------+

b didn't change, the object changed. So naturally if we did console.log(a.question);, we'd see the famous question, because a and b point to the same object.

If we actually change b, it has no effect on a at all:

b = {foo:"bar"};
                  +------------+
[b:REF14359]----->|  (object)  |
                  +------------+
                  | foo: "bar" |
                  +------------+

                  +------------------------------------------------+
[a:REF55134]----->|                   (object)                     |
                  +------------------------------------------------+
                  | answer: 42                                     |
                  | question: "Life, the Universe, and Everything" |
                  +------------------------------------------------+

Note that now b has a different value in it, referring to a different object.