При решении задач в массиве JavaScript-разработчики могут столкнуться с ошибками, используя метод push
для добавления элемента. Проблема возникает при создании ПО на JavaScript и React.
Разберем побочные эффекты метода push
на двух примерах. Чтобы было более понятно, возьмем для демонстрации небольшие фрагменты кода.
Пример 1
function push(a) {
b = a;
b.push(4);
console.log("Duplicate- ", b);
}
const a = [1,2,3];
push(a); //Вывод:- Дубликат- [1, 2, 3, 4]
//Что если задействовать console.log(a) после вызова функции?
console.log("original", a); //Вывод:- оригинал- [1, 2, 3, 4]
Использование метода push
приводит к изменению массива Original
. Рассмотрим возможные способы устранения этого побочного эффекта, которые позволят избежать изменения исходного массива.
Решение
Для устранения побочного эффекта будем использовать оператор spread
.
function push(a) {
const b = [...a, 4] //Использование [spread operator, 4] для добавления элемента.
console.log(b)
}
const a = [1,2,3]
push(a) //Вывод:- Дубликат- [1, 2, 3, 4]
//Что если задействовать console.log(a) после вызова функции?
console.log("original", a) //Output:- original- [1, 2, 3]
Представьте, что создаете онлайн-магазин, в котором можно добавлять товар в корзину. Почему не стоит использовать метод push
?
Пример 2
//Массив объектов
//3 элемента внутри исходного массива.
const cart = [
{
name: 'The Foundation Trilogy',
price: 19.99,
discount: false,
},
{
name: 'Godel, Escher, Bach',
price: 15.99,
discount: false,
},
{
name: 'Red Mars',
price: 5.99,
discount: true,
}, ];
const reward = {
name: 'Guide to Science Fiction',
discount: true,
price: 0,
};
function addFreeGift(cart) {
if (cart.length > 2) {
cart.push(reward)
return cart
}
return cart;
}
function summarizeCart(cart) {
const cartWithReward = addFreeGift(cart);
// возвращаемый результат addFreeGit(cart) сохраняется в CartWithReward
console.log(cartWithReward)
const discountable = cart.filter(item=>item.discount);
// товар со скидкой = [ {discount: true }, {discount: true} ]
if (discountable.length > 1) {
return {
error: 'Can only have one discount',
};
}
return {
discounts: discountable.length,
items: cartWithReward.length,
cart: cartWithReward,
};
}
console.log("Add free gift:");
console.log(addFreeGift(cart));
console.log("\n");
console.log("Summarize cart:");
console.log(summarizeCart(cart));
console.log("\n");
console.log("Cart:");
console.log(cart);
Вывод для приведенного выше кода:
//Вывод
Add free gift:
0:{name: 'The Foundation Trilogy', price: 19.99, discount: false}
1: {name: 'Godel, Escher, Bach', price: 15.99, discount: false}
2: {name: 'Red Mars', price: 5.99, discount: true}
3: {name: 'Guide to Science Fiction', discount: true, price: 0}
4: {name: 'Guide to Science Fiction', discount: true, price: 0}
//Вывод
Summarize cart:
0:{name: 'The Foundation Trilogy', price: 19.99, discount: false}
1: {name: 'Godel, Escher, Bach', price: 15.99, discount: false}
2: {name: 'Red Mars', price: 5.99, discount: true}
3: {name: 'Guide to Science Fiction', discount: true, price: 0}
4: {name: 'Guide to Science Fiction', discount: true, price: 0}
{error: 'Can only have one discount'}
//Вывод
Cart:
0:{name: 'The Foundation Trilogy', price: 19.99, discount: false}
1: {name: 'Godel, Escher, Bach', price: 15.99, discount: false}
2: {name: 'Red Mars', price: 5.99, discount: true}
3: {name: 'Guide to Science Fiction', discount: true, price: 0}
4: {name: 'Guide to Science Fiction', discount: true, price: 0}
Как видите, вывод Add free gift
, Summarize cart
и Cart
сопровождается побочными эффектами: одни и те же товары добавляются дважды, при этом исходные товары в корзине меняются.
Чтобы избежать этих побочных эффектов, будем использовать оператор spread
внутри функции addFreeGift
для корзины.
function addFreeGift(cart) {
if (cart.length > 2) {
//Ранее использовалось cart.push(reward)
cart = [...cart, reward]
return cart
}
return cart;
}
Теперь вывод будет выглядеть следующим образом:
//Вывод
Add free gift:
0:{name: 'The Foundation Trilogy', price: 19.99, discount: false}
1: {name: 'Godel, Escher, Bach', price: 15.99, discount: false}
2: {name: 'Red Mars', price: 5.99, discount: true}
3: {name: 'Guide to Science Fiction', discount: true, price: 0}
//Вывод
Summarize cart:
0:{name: 'The Foundation Trilogy', price: 19.99, discount: false}
1: {name: 'Godel, Escher, Bach', price: 15.99, discount: false}
2: {name: 'Red Mars', price: 5.99, discount: true}
3: {name: 'Guide to Science Fiction', discount: true, price: 0}
{error: 'Can only have one discount'}
//Вывод
Cart:
0: {name: 'The Foundation Trilogy', price: 19.99, discount: false}
1: {name: 'Godel, Escher, Bach', price: 15.99, discount: false}
2: {name: 'Red Mars', price: 5.99, discount: true}
Читайте также:
- Визуализация map, filter и reduce
- Эта информация навсегда изменит ваше отношение к коду JavaScript
- Где (и почему) следует использовать стрелочные функции ES6, а где не следует
Читайте нас в Telegram, VK и Дзен
Перевод статьи Ajmal Ali: Why we should avoid the push method in JavaScript