2
    var eData = [
  [
    ['firstName', 'Joe'],
    ['lastName', 'Blow'],
    ['age', 42],
    ['role', 'clerk']
  ],
  [
    ['firstName', 'Mary'],
    ['lastName', 'Jenkins'],
    ['age', 36],
    ['role', 'manager']
  ]
];

var employees = [];
var person = {};

function transformEmployeeData(employeeData){
    for(i=0; i < employeeData.length; i++){
        for(j=0; j < employeeData[i].length; j++){
            var key = employeeData[i][j][0];
            var value = employeeData[i][j][1];
            person[key] = value;
            employees[i] = person;
        }
    }
    return employees;
}
console.log(transformEmployeeData(eData));

Returns the following:

[ { firstName: 'Mary',
    lastName: 'Jenkins',
    age: 36,
    role: 'manager' },
  { firstName: 'Mary',
    lastName: 'Jenkins',
    age: 36,
    role: 'manager' } ]

Why is Mary employees[0] and employees[1]?

Declaring the person object inside the first for loop fixes the problem. But why?

Why does putting the person object inside the second for loop:

function transformEmployeeData(employeeData){
    for(i=0; i < employeeData.length; i++){
        for(j=0; j < employeeData[i].length; j++){
            var person = {};
            var key = employeeData[i][j][0];
            var value = employeeData[i][j][1];
            person[key] = value;
            employees[i] = person;
        }
    }
    return employees;
}

Return only the following?

[ { role: 'clerk' }, { role: 'manager' } ]
1
  • It's not about the variable declaration, it's about the object creation. Inside the loop, the object literal will be evaluated multiple times and create multiple distinct objects; outside the loop only one object is instantiated which is referenced everywhere. Commented Jan 10, 2017 at 23:27

3 Answers 3

2

When you declare person at the global scope in the first example, you are defining an object visible to all the code in your script. Your loops basically just end up changing one property of this one variable with each iteration of the inner loop. It's the same variable every time, just with different values assigned -- and every item in the array employees points to this one object.

In the second example, the var person is declared within the for block -- and it does not exist outside this block. Moreover, the var is redeclared as a new, distinct variable for each iteration of the loop in which it is declared.

Javascript is smart enough in the second case to persist the object assigned to the person variable even after person itself is garbage-collected.

These are basic concepts in Javascript scope. You'll probably find some informative discussion of Javascript scope in the MDN article on var.

EDIT: additional info about stuff I'd overlooked:

You also need to be careful about where you declere person and what you are assigning in your loop. If you declare person in your innermost loop, it gets repeatedly destroyed and then instantiated again, retaining only one property at a time:

when j=0, it creates person={firstname:"Mary"}, this gets assigned to employees[i] and then gets destroyed

when j=1, it creates person={lastname:"Jenkins}, this gets assigned to employees[i] and then gets destroyed

when j=2, it creates person={age:36}, this gets assigned to employees[i] and then gets destroyed

when j=3, it creates person={role:"manager"}, this gets assigned to employees[i] and then gets destroyed

Then it exits the inner loop, with employees[i] retaining that last assignment.

Sign up to request clarification or add additional context in comments.

3 Comments

Actually the problem is that the variable is not changed, it holds the same object always.
No the problem is that it is changed over and over, and just ends up retaining the last value it got assigned in the loop, which will be the last element in your array.
The properties of the object are changed, the variable is not.
0

In JavaScript, a variable name refers to a location in a memory environment holding a value.

In the first version, the person variable only references one location the entire time, and as a result can only hold one value. As a result, upon multiple iterations, it's properties are overwritten and only the last value remains. This means all references to this location (i.e. employees[i] = person;) end up with the last value.

In the second version, the person variable references a different location each iteration because it is assigned a new memory location using var person = {}; in the for loop. As a result, each reference to the person location in the same loop (i.e. employees[i] = person;) end up with that loop's value.

2 Comments

The person variable is never overwritten. The object's contents (property values) are.
@Bergi - I clarified that.
0

Because person is declared as a global, and you just overwrite its properties.

You could reassign a new object, but what would be the point? Just declare at the proper place.

var eData = [
  [
    ['firstName', 'Joe'],
    ['lastName', 'Blow'],
    ['age', 42],
    ['role', 'clerk']
  ],
  [
    ['firstName', 'Mary'],
    ['lastName', 'Jenkins'],
    ['age', 36],
    ['role', 'manager']
  ]
];
function transformEmployeeData(employeeData){
  var employees = [];
  for(var i=0; i < employeeData.length; i++) {
    var person = {};
    for(var j=0; j < employeeData[i].length; j++){
      var key = employeeData[i][j][0];
      var value = employeeData[i][j][1];
      person[key] = value;
    }
    employees[i] = person;
  }
  return employees;
}
console.log(transformEmployeeData(eData));

3 Comments

The script could still work if the person variable was declared globally, it only is important that a new object is assigned to it on every iteration.
@Bergi It would work but it would be horrendous. Argh, I have just noticed various implicit globals!
Sure, my comment was meant only to criticise the first sentence in your answer as inaccurate.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.