简体   繁体   中英

What is the correct way of pushing an object into an array?

I have been trying different methods to add simple coordinates as objects {x:0, y:1} into an array, and it works if I add them manually, so to speak.

But if I'm using a loop, the result defies my understanding. The resulting array has all objects that were pushed from inside the loop hold the exact same values as the last pushed object.

function(){
  var plot = ['south','east','north','east','north'] // user input
  let records = [ // the array, with an initial object
    {x: 0, y: 0}
  ];
  var step ={ // object to modify and copy into array
    x: 0,
    y: 0,
  };
  for (var i = 0; i < plot.length; i++) {
    if (plot[i] == "north"){
      step.y++;
    }
    if (plot[i] == "east"){
      step.x++;
    }
    if (plot[i] == "south"){
      step.y--;
    }
    if (plot[i] == "west"){
      step.x--;
    }
    console.log(step.x+','+step.y); // shows that the data is correctly modified
    records.push(step);
    console.log(records.length); // shows that the object was added to the array
  }
  for (var i = 0; i < records.length; i++) {
    var newItem = records[i];
    console.log('newItem: x='+newItem.x+' y='+newItem.y);
  }
}

Furthermore, in the example above, the array's length is considered to be 2 even though it clearly reached 6 during the execution of the loop.

I can't tell if there's an error in logic, or my computer is playing tricks on me.

You need to initialize step inside your for loop:

    var plot = ['south', 'east', 'north', 'east', 'north'] // user input
    let records = [ // the array, with an initial object
        { x: 0, y: 0 }
    ];

    for (var i = 0; i < plot.length; i++) {
        var step = { // object to modify and copy into array
            x: i > 0 ? records[i-1].x : 0,
            y: i > 0 ? records[i-1].y : 0,
        };
        if (plot[i] == "north") {
            step.y++;
        }
        if (plot[i] == "east") {
            step.x++;
        }
        if (plot[i] == "south") {
            step.y--;
        }
        if (plot[i] == "west") {
            step.x--;
        }
        console.log(step.x + ',' + step.y); // shows that the data is correctly modified
        records.push(step);
        console.log(records.length); // shows that the object was added to the array
    }

    console.log(records);

You could take just x and y for changing, depending on the direction an add a new object to records .

 function go() { var plot = ['south', 'east', 'north', 'east', 'north'], x = 0, y = 0, records = [{ x, y }]; for (var i = 0; i < plot.length; i++) { switch (plot[i]) { case "north": y++; break; case "east": x++; break; case "south": y--; break; case "west": x--; break; } records.push({ x, y }); } return records; } console.log(go());
 .as-console-wrapper { max-height: 100% !important; top: 0; }

It's happening because the step variable is holding a reference to the object, not the object itself so each time you do

records.push(step);

you are appending the same reference to the same object . And in each iteration, you are modifying the same object using the same reference . This is why all of your elements in the records array have the same values inside. In order to fix this, you can either initialize step in each iteration:

for (var i = 0; i < plot.length; i++) {
    var step = { // object to modify and copy into array
        x: 0,
        y: 0,
    };
    if (plot[i] == "north") {
        step.y++;
    }
    if (plot[i] == "east") {
        step.x++;
    }
    if (plot[i] == "south") {
        step.y--;
    }
    if (plot[i] == "west") {
        step.x--;
    }
    console.log(step.x + ',' + step.y); // shows that the data is correctly modified
    records.push(step);
    console.log(records.length); // shows that the object was added to the array
}

or you can push to the array a copy of the object:

var step = { // object to modify and copy into array
    x: 0,
    y: 0,
};
for (var i = 0; i < plot.length; i++) {

    if (plot[i] == "north") {
        step.y++;
    }
    if (plot[i] == "east") {
        step.x++;
    }
    if (plot[i] == "south") {
        step.y--;
    }
    if (plot[i] == "west") {
        step.x--;
    }
    console.log(step.x + ',' + step.y); // shows that the data is correctly modified

    /* ---> */ records.push(Object.assign({}, step)); // copy the object

    console.log(records.length); // shows that the object was added to the array
}

You need to push a clone of step , otherwise the previous step is overwritten.

 function plotter(){ var plot = ['south','east','north','east','north'] // user input let records = [ // the array, with an initial object {x: 0, y: 0} ]; var step ={ // object to modify and copy into array x: 0, y: 0, }; for (var i = 0; i < plot.length; i++) { if (plot[i] == "north"){ step.y++; } if (plot[i] == "east"){ step.x++; } if (plot[i] == "south"){ step.y--; } if (plot[i] == "west"){ step.x--; } console.log(step.x+','+step.y); // shows that the data is correctly modified var clone = Object. assign({}, step); records.push(clone); console.log(records.length); // shows that the object was added to the array } for (var i = 0; i < records.length; i++) { var newItem = records[i]; console.log('newItem: x='+newItem.x+' y='+newItem.y); } } plotter();

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