Недавно в браузерах появился новый совместимый метод, который можно вызывать для массивов: Array.prototype.with() .
В этой статье рассматривается, как работает этот метод и как использовать его для обновления массива без изменения исходного массива.
Введение в Array.prototype.with(index, value)
Метод Array.prototype.with(index, value) возвращает копию вызванного им массива с index , установленным в новое предоставленное вами value .
В следующем примере показан массив возрастов. Вы хотите создать новую копию массива, изменив второй возраст с 15 на 16:
const ages = [10, 15, 20, 25];
const newAges = ages.with(1, 16);
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)
Разбивка кода: ages.with(...) возвращает копию переменной ages без изменения исходного массива. ages.with(1, …) заменяет второй элемент ( index = 1 ). ages.with(1, 16) присваивает второму элементу значение 16 .
Вот как вы смогли создать новую копию массива с модификацией.
Это очень полезно, когда вы хотите убедиться, что исходный массив остается неизменным, и в этой статье рассматриваются некоторые варианты использования этого. А пока посмотрите, что произошло бы, если бы вы использовали скобочные обозначения:
const ages = [10, 15, 20, 25];
const newAges = ages;
newAges[1] = 16;
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 16, 20, 25] (Also changed 🙁)
Как видите, в этом примере также была изменена переменная ages . Это потому, что когда вы назначаете ages = newAges , JavaScript не копирует массив, а создает ссылку на другой массив. Таким образом, любое изменение в одном также повлияет на другое, поскольку они оба указывают на один и тот же массив.
Array.prototype.with() и неизменность
Неизменяемость лежит в основе многих интерфейсных библиотек и фреймворков, среди которых можно назвать React (и Redux) и Vue.
Кроме того, другие библиотеки и фреймворки не обязательно требуют неизменяемости, но поощряют ее для повышения производительности: Angular и Lit.
Поэтому разработчикам часто приходилось использовать другие методы, возвращающие копии массивов, что жертвовало читабельностью кода:
const ages = [10, 15, 20, 25];
const newAges = ages.map((age, index) => {
if (index === 1) {
return 16;
}
return age;
});
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (Remains unchanged)
Вот пример Codepen того, как .with() можно использовать в React в сочетании с useState для неизменного обновления массива элементов:
Поскольку метод .with() возвращает копию массива, вы можете объединить несколько вызовов .with() или даже других методов массива. В следующем примере показано увеличение второго и третьего возраста из массива:
const ages = [10, 15, 20, 25];
const newAges = ages.with(1, ages[1] + 1).with(2, ages[2] + 1)
console.log(newAges); // [10, 16, 21, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)
Другие новые неизменяемые методы
Недавно стали совместимыми три других метода:
-
Array.prototype.toReversed(), который переворачивает массив без изменения исходного массива. -
Array.prototype.toSorted(), который сортирует массив без изменения исходного массива. -
Array.prototype.toSpliced(), который работает как.splice(), но без изменения исходного массива.
По мнению MDN, эти три метода являются копирующей версией своих аналогов. Эти методы также можно использовать там, где ожидается или предпочтительна неизменность.
В заключение отметим, что неизменяемых обновлений в JavaScript можно легче добиться с помощью одного из четырех методов, представленных в этой статье. В частности, метод .with() упрощает обновление одного элемента массива без изменения исходного массива.