5

The revision of the MDN guide on working with objects from July 15th, 2014, states:

If an object is created with an object initializer in a top-level script, JavaScript interprets the object each time it evaluates an expression containing the object literal.

However, in the snippet below, when objLit2.val2 is evaluated, it does not use the last value set which should be 10 and 100; it instead uses 1000 which was the value declared when objLit2 is defined. Why is it so?

var i = 1000;

function iPlus3() {
  alert("iPlus3");
  
  return i + 3;
}

var objLit2 = {
  val: iPlus3,
  val2: i = i + 1
};

function setValue() {
  i = 10;
  console.log("objLit2Val1", objLit2.val(), objLit2.val2); // Outputs 13 1001 and not 13 11
  
  i = 100;
  console.log("objLit2Val2", objLit2.val(), objLit2.val2); // Outputs 103 1001 and not 103 101
  
  // If `val` is interpreted at the time of the call, why is `val2` not also interpreted on each call?
}

setValue();
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Ankit
  • 153
  • 1
  • 6

4 Answers4

2

objLit2 is a top level declaration. Thus, it is evaluated as your script is first executed. Once it is evaluated, the property objLit2.val2 will have its value set. It won't get a different value just because you refer to objLit2 somewhere else in your code unless you consciously change the value of the property objLit2.val2.

Once objLit2 has been evaluated, the property objLit2.val2 contains a primitive number that no longer has any connection to the variable i. The value of objLit2.val2 stands on its own and its value will not be effected by changes to any other variables.

Primitives in javascript (like numbers and booleans) are stored as distinct values that have no connection to any other variables. Objects in javascript are stored as references to the original object. Since objLit2.val2 is a number, it is just an independent value that stands on it's own.

So, you can do this:

var i = 1000;
var objLit2 = { val : iPlus3, val2 : i = i + 1 };
console.log(objLit2.val2);    // shows 1001
i += 1000;
console.log(objLit2.val2);    // still shows 1001

Objects on the other hand, are stored as a reference to the original object. So, if you did this:

var indexes = [1,2,3];
var objLit2 = { val : indexes, val2 : i = i + 1 };
console.log(objLit2.indexes);    // shows [1,2,3]
indexes[0] = 0;
console.log(objLit2.indexes);    // shows [0,2,3]

Because an array is an object so when you specify the array in the objLit2 literal, it is just storing a reference to that array (not a separate copy of the array). If you change that original array, you will see that change in all other variables that contain a reference to that array.


What it sounds like you are quoting would apply to objects that are declared within some scope (like inside a function) because they will be reevaluated each time that scope is created (e.g. each time the function is run).

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • In case of val2 it is the value ( i.e.) 1001 stored and in case of val it is the pointer to the function that is stored. When "JavaScript interprets the object each time _to_ evaluate the expression" objLit2, 1001 remains 1001 only, However the value of function referenced by that same location comes to 13 and 103 in the two calls. – Ankit Jul 19 '14 at 05:22
1

In your initializer, i is incremented once and then its value is stored in objLit2.val2. Since i is a primitive type - a number - objLit2.val2 is a distinct variable from i.

This is in contrast to a situation where one object is set equal to another.

var objLit3 = objLit2;
objLit2.val2 = 5;
console.log(objLit2.val2); // Also 5

In the example here, objLit3 holds a new reference to the same underlying object, rather than creating a new instance. That doesn't happen with numbers. Each new variable assigned a number is a new instance in memory.

Austin Mullins
  • 7,307
  • 2
  • 33
  • 48
0

When JavaScript creates object literals, the key has some value. That value could be a function, number, etc... In your case, you're providing something to be evaluated for the value right away... for example this is somewhat equivalent to what's happening:

var i = 1000;

function demo() {
    return i = i + 1;
}

var objLit2 = {
    val2: demo()
};
Robert
  • 667
  • 7
  • 15
0

Let's step through a summarized version of your code. What is shown on the right is what's stored in the variables at each statement.

var i = 1000;                                   // i = 1000
var objLit2 = { val: iPlus3, val2: i = i + 1 }; // i = 1001, objLit2.val2 = 1001

i = 10;                                         // i = 10, objLit2.val2 = 1001
innerHTML = (i + 3).toString() + ' ' + '1001';  // Outputs: 13 1001
i = 100;                                        // i = 100, objLit2.val2 = 1001
innerHTML = (i + 3).toString() + ' ' + '1001';  // Outputs: 103 1001

It seems you are thinking the statement val2 : i = i + 1 means that a reference to i is assigned to val2. That's not the case as number types in javascript are immutable. What that means is when an object (like i and objLit2) is assigned a number, it will always store the value of that number and not the reference.

For example:

var i, val2;
i = 1000;  // i = 1000
i = i + 1; // i = 1001
val2 = i;  // i = 1001, val2 = 1001
val2++;    // i = 1001, val2 = 1002

Take note of the following with object types (works this way because it is assigning an object type and not a number type):

var objectType  = { numType: 14 }, // objectType  = { numType: 14 }
    otherObject = objectType;      // otherObject = &objectType; (reference to)

// So the following statement...
otherObject.numType = 15;          // objectType  = { numType: 15 };
// ...is equivalent to:            // otherObject = &objectType; (reference to)
objectType.numType = 15;
// since:
otherObject == objectType;
Community
  • 1
  • 1
David Sherret
  • 101,669
  • 28
  • 188
  • 178