Почему стоит избегать метода push при разработке на JavaScript

При решении задач в массиве 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}

Читайте также:

Читайте нас в TelegramVK и Дзен


Перевод статьи Ajmal Ali: Why we should avoid the push method in JavaScript

Предыдущая статья8 полезных функций Angular, о которых стоит знать
Следующая статьяРеализация цифрового конверта в iOS