Copy an array and replace one element at a specific index with modern JavaScript
- 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.
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?
All modern browsers support with()
these days.
110 | 110 | 110 | 115 | 115 | 16 | 16 | 21.0 | 110 |
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!
Join 5.5k readers and learn something new every week with Web Weekly.