Published at
Updated at
Reading time
3min

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, 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 newArray.push(newValue); 

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

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

But this isn't great. Changing an array entry with map is slightly better...

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(numbers);                    // [1, 2, 3, 4, 5]
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 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(numbers);                    // [1, 2, 3, 4, 5]
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 a single 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(numbers);                    // [1, 2, 3, 4, 5]
console.log(updatedNumbers);             // [1, 'new value', 3, 4, 5]
console.log(numbers === updatedNumbers); // false

Thank you modern JavaScript!

If you enjoyed this article...

Join 5.5k readers and learn something new every week with Web Weekly.

Web Weekly — Your friendly Web Dev newsletter
Reply to this post and share your thoughts via good old email.
Stefan standing in the park in front of a green background

About Stefan Judis

Frontend nerd with over ten years of experience, freelance dev, "Today I Learned" blogger, conference speaker, and Open Source maintainer.

Related Topics

Related Articles