Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is an expression in an object initializer not re-evaluated each time the property is read?

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();
like image 670
Ankit Avatar asked Oct 21 '22 05:10

Ankit


1 Answers

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).

like image 105
jfriend00 Avatar answered Oct 23 '22 03:10

jfriend00