Published at
Updated at
Reading time
2min

How do you replace an array element at a given index?

Is this a trick question? Not really.

const numbers = [1, 2, 3, 4, 5];
numbers[1] = 'new value';
console.log(numbers); // [1, 'new value', 3, 4, 5]

But when you're using React or any framework betting on immutability, just changing an array entry will lead to subtle bugs because the array will still be the same object with the same reference. In an immutable world, data updates always have to result in a new object reference.

How can you change an array element via its index and spit out a new array in the same go then? A 12-years-old Stack Overflow question with 1.5m views has tons of advice, but because it's so old and has hundreds of upvotes, it's not showing the most modern solution in the top area.

Let's have a quick look at creative answers.

The old way to copy an array and change one item

You certainly could iterate over the array and build up a new one with a good old forEach loop.

function changeItem(array, index, newValue) {
  const newArray = [];
  array.forEach((num, i) => {
    if (i === index ) return newNumbers.push(newValue); 

    newArray.push(num);
  })
  return newArray;
}

const numbers = [1, 2, 3, 4, 5];
const updatedNumbers = changeItem(numbers, 1, 'new value');
console.log(updatedNumbers);             // [1, 'new value', 3, 4, 5]
console.log(numbers === updatedNumbers); // false

But this isn't great. Doing it with map is already a bit nicer...

function changeItem(array, index, newValue) {
  return array.map((value, i) => {
    if (i === index) return newValue;

    return value;
  })
}

const numbers = [1, 2, 3, 4, 5];
const updatedNumbers = changeItem(numbers, 1, 'new value');
console.log(updatedNumbers);              // [1, 'new value', 3, 4, 5]
console.log(numbers === updatedNumbers);  // false

And for the creatives, if you belong to this small group of folks who remember the difference between slice and splice, you could also use one of these.

function changeItem(array, index, newValue) {
  return [
    ...array.slice(0, index),
    newValue,
    ...array.slice(index + 1)
  ];
}

const numbers = [1, 2, 3, 4, 5];
const updatedNumbers = changeItem(numbers, 1, 'new value');
console.log(updatedNumbers);             // [1, 'new value', 3, 4, 5]
console.log(numbers === updatedNumbers); // false

Okay, this one (☝️) is actually terrible.

But what if I told you that copying an array and changing one entry is cross-browser supported in JavaScript today?

The new way — copy an array and change an entry with with()

All modern browsers support with() these days.

MDN Compat Data (source)
Browser support info for Array.with()
chromechrome_androidedgefirefoxfirefox_androidsafarisafari_iossamsunginternet_androidwebview_android
110110110115115161621.0110

And with it, this entire exercise becomes a nifty one-liner.

const numbers = [1, 2, 3, 4, 5];
const updatedNumbers = numbers.with(1, 'new value');
console.log(updatedNumbers);             // [1, 'new value', 3, 4, 5]
console.log(numbers === updatedNumbers); // false

Thank you modern JavaScript!

Was this snippet helpful?
Yes? Cool! You might want to check out Web Weekly for more snippets. The last edition went out 1 days ago.

Related Topics

Related Articles

About the author

Stefan standing in the park in front of a green background

Frontend nerd with over ten years of experience, "Today I Learned" blogger, conference speaker, Tiny helpers maintainer, and DevRel at Checkly.