简体   繁体   中英

JS - I don't understand why this declaration of object doesn't work

I'm just starting out learning some JS and I have a very simple but confusing question. I've tried to debug my code to see how this works and why it works the way it does but I just don't get it. Below I have my function along with a sample input of employeeData .

function transformEmployeeData(employeeData) {
  var result = [];
  var obj = {};
  for (var i = 0; i < employeeData.length; i++) {
    for (var j = 0; j < employeeData[i].length; j++) {
      obj[employeeData[i][j][0]] = employeeData[i][j][1];
    }
    result.push(obj);
  }
  return result;
}

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

/* Expected Results -
[
    {firstName: 'Joe', lastName: 'Blow', age: 42, role: 'clerk'},
    {firstName: 'Mary', lastName: 'Jenkins', age: 36, role: 'manager'}
] 

Actual Results - 
[
    {firstName: 'Mary', lastName: 'Jenkins', age: 36, role: 'manager'},
    {firstName: 'Mary', lastName: 'Jenkins', age: 36, role: 'manager'}
]*/

I know how to fix my code to get the desired results by moving the var obj = {}; line right after the for loop of i . What I don't understand is why does the above code not work? After the i = 0 finishes, the obj holds the first expected input and pushes it into the result array. But then it pushes the Mary array and over writes the rest and I end up with the actual result. Couple of questions. Why does my initial object that is correct holding data of Joe disappear from my array and why does the object holding the Mary data get put in twice? If I'm understanding my code correctly; the for loop for i should only iterate twice meaning that there should only ever be two objects pushed into it but why do I end up with 2 Mary objects inside? And lastly why does the declaration of a new object variable need to be inside the initial for loop?

Since you are learning, here is my 2c to your learning journey. Instead of endless nested loops, try to embrace the gems of functional programming, namely, Array.prototype.map and Array.prototype.reduce . Using them, you can achieve what you were doing in a much more elegant (and often times, faster) manner:

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

var transformedInput = input.map(function(el) {
    return el.reduce(function(result, elel) {
        result[elel[0]] = elel[1];
        return result;
    }, {});
})

Your code has only one mistake otherwise it is ok,

JavaScript Objects are passed by reference , but you are pushing the same Object in every iteration, so the next object overrides the last one and you got the same object in all iteration.

So what you have to do is declare var obj; outside the loop and put the obj = {}; inside the first for loop, so that a new object is created each time loop iterates ,

See my below working example:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM