7

I have an array of objects with length n and I want to extend it to the length n+1. For ease of use I would like to duplicate the last element and then change the properties of the duplicate.

let arr = [{id: 1, name: 'foo'}, {id: 2, name: 'bar'}];

arr.push(arr[1]);       // extend by copying the last
arr[2].id += 1;         // change the id of the new last
arr[2].name = 'foobar'; // change the name of the new last

console.log(arr);

In the snippet above (use the browser console as snippet console is behaving kinda weird here) is what I've tried but for some reason any change to the copied/new last element is also applied to the original/old last/new second-last element in the array.

How can I properly do this and why does my code behave in the way it does?

leonheess
  • 10,362
  • 9
  • 56
  • 89
  • 1
    `arr.push(arr[1]); ` – briosheje Jul 29 '19 at 13:25
  • 1
    @MiXT4PE, `arr.push({ ...arr[1] }); ` – lucifer63 Jul 29 '19 at 13:27
  • 1
    wouldn't it just be easier to push en empty object - arr.push({}) - and update that? – Lee Willis Jul 29 '19 at 13:27
  • Is this really a duplicate? The answers seem to be different.. – leonheess Jul 29 '19 at 13:32
  • @LeeWillis this is a mvce - the real object is more complex and I creating it from scratch every time would be a lot of code – leonheess Jul 29 '19 at 13:33
  • 1
    @MiXT4PE This is technically a duplicate because the real problem here is **duplicating an object**. I'm personally aware that the question is rather "how to duplicate the last element of an array" but, really, the real problem here is that you are **not** cloning the element and, hence, the question becomes "how to properly clone an object", which has already a whole lot of answers. The question is clearly exposed and your effort is actually visible, though, which is good. – briosheje Jul 29 '19 at 13:35

2 Answers2

3

You could push a copy of the object and omit the same object reference.

let arr = [{id: 1, name: 'foo'}, {id: 2, name: 'bar'}];

arr.push({ ...arr[1] }); // extend by copying the last
arr[2].id += 1;          // change the id of the new last
arr[2].name = 'foobar';  // change the name of the new last

console.log(arr);
Nina Scholz
  • 351,820
  • 24
  • 303
  • 358
  • Thank you! I will accept as soon as I can. Maybe also explain how `...arr[1]` creates a copy – leonheess Jul 29 '19 at 13:28
  • 2
    `...arr[1]`, spreads all the keys and values from the existing object into a new one, that's why you are not having that issue with referencing anymore, good answer :) – Nicolae Maties Jul 29 '19 at 13:30
  • 2
    Also please be careful while cloning with spread operator. It goes only 1 level deep with cloning. In your case its fine. – ambianBeing Jul 29 '19 at 13:36
1

const arr = [{id: 1, name: 'foo'}, {id: 2, name: 'bar'}];
const lastEl = Object.assign({}, arr[1]);
lastEl.id = 4;
lastEl.name = 'foo';
arr.push(lastEl);
console.log(arr);
Nicolae Maties
  • 2,214
  • 1
  • 11
  • 22