1

Question:

Why does the declaration of the obj variable have to move to the "//MOVE TO HERE" location below to properly produce an array of both the {number: 1, color: blue} and {number: 2, color: red} objects? When the declaration stays in its current spot below, the array results in {number: 2, color: red}, {number: 2, color: red} (i.e. the same object, twice)

My understanding:

In its current position, the arrObj array is updated with the most current value of obj, so the output is an array that twice lists "number: 2, color: red".

Confusion:

How come both objects appear in the array when the obj declaration is moved to //MOVE TO HERE below? If the array is dynamically updated with each update of obj, why is arrObj[0] not cleared and then updated with the new values of obj when obj is declared a second time?

     function arrayOfObjects(array) {
            var arrObj = [];
            var obj = {};

            for (i = 0; i < array.length; i++) {
              //MOVE TO HERE
                for (j = 0; j < array[i].length; j++) {
                    obj[array[i][j][0]] = array[i][j][1];
                }
                arrObj[i] = obj;
            }
            return arrObj;
        }

var array = [ [ ['number', '1'], ['color', 'blue'] ] , ['number', '2'], ['color', 'red'] ] ]
arrayOfObjects(array);
user3794585
  • 203
  • 1
  • 11
  • 2
    This doesn't have anything to do with scope, the code is semantically different. In the second case you're instantiating and assigning a new empty object on every outer iteration. – pvg Jun 28 '17 at 00:24
  • 1
    In its current location `obj` contains a reference to the same object during all assignments to `arrObj[i]`. When `arrObj[i] = obj;` is executed, the contents of `obj` are not being added to `arrObj` but rather a REFERENCE to `obj`. So when `obj` is reused in subsequent iterations, `obj` is updated and a new reference to it is added to `arrObj`. Both elements of `arrObj` are references to the SAME OBJECT! So they will both contain the last value of `obj`. By moving the declaration inside the loop, you are creating a new object each time, and adding a new object to `arrObj` each time. – RJM Jun 28 '17 at 00:26
  • 2
    If you leave the declaration where it is and (and skip the initialization, if you want) and then put `obj = {};` at `// MOVE TO HERE` you'll get results identical to the second run. So you can see it's not about where the declaration is. – pvg Jun 28 '17 at 00:32
  • *"How come both objects appear in the array when the obj declaration is moved to //MOVE TO HERE below?"* `var` declarations are not block scoped the are *function scoped*. Meaning it doesn't matter where you put a `var` declaration inside the function, it will always behave as if the variable was declared at the top of the function (the *initialization* still happens where it appears in code). – Felix Kling Jun 28 '17 at 01:30

1 Answers1

-1

In JavaScript objects passing by reference can take place. In this case that means arrObj and obj is referencing to the same object in memory. So when in second iteration obj has been mutated { number: 12, color: red } arrObj[0] and arrObj[1] both referencing to the same object. SO discussion

  • 2
    Careful with the terminology here. Pass by reference does not mean representing objects *as* references. *Pass by ...* describes the relationships between *bindings*, not between bindings and values. As such, JavaScript is *pass by value*. In case of objects that value is a reference to the object. More info: https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_reference – Felix Kling Jun 28 '17 at 01:28
  • Thank you Felix, thats absolutely right. I will update the answer. – jillionbug2fix Jun 28 '17 at 01:34
  • 1
    Also include and comment the code, don't post a giant screenshot of code. It's bad enough when that's done in questions. – pvg Jun 28 '17 at 01:43