Использование операторов спреда и остальных параметров

Мутирующие массивы

Когда вы передаете массив в функцию в JavaScript, он передается как ссылка. Все, что вы делаете, чтобы изменить массив внутри функции, также изменит исходный массив. например, этот код выведет [1, 2, 3] на консоль:

var array = [1, 2, 3, 4];
const mutate = arr => {
 arr.pop();
 return arr;
}
mutate(array);
console.log(array); // result [1, 2, 3]

копирование переданного массива в новый массив и выполнение всей обработки в новом массиве не помогает:

var array = [1, 2, 3, 4];
const mutate = arr => {
 var newArr = arr;
 newArr.pop();
 return newArr;
}
mutate(array);
console.log(array); // result [1, 2, 3] - Still mutated!

Это происходит потому, что var newArr = arr; не создает новый массив. Все это указывает новую переменную на тот же массив.

Вы можете использовать Array.from:

var newArr = Array.from(arr);

или срез():

var newArr = arr.slice();

чтобы скопировать массив, переданный в функцию, в новый массив. Затем вы можете изменить новый массив, не изменяя исходный массив.

… Другой способ…

Сегодня утром я просматривал определение остальных параметров и операторов распространения, и мне пришло в голову, что есть другой способ передать массив как значение вместо ссылки.

Параметр rest позволяет нам представить неопределенное количество аргументов в виде массива. Когда вы определяете функцию, используя остаточный параметр, аргументы функции, независимо от их количества, будут преобразованы в массив.

оператор распространения позволяет расширять итерируемый объект, например массив, на месте. Если вы используете оператор распространения при передаче массива в вызов функции, функция получит отдельные значения массива в качестве аргументов.

Если мы объединим эти две концепции, определив нашу функцию с оставшимся параметром и вызвав функцию с оператором распространения, мы сможем выполнять операции над массивом с помощью функции, не изменяя исходный массив.

var array = [1, 2, 3, 4];
// use rest parameter in function definition
// to turn passed values into array
const noMutate = (…arr) => {
 arr.pop();
 return arr;
}
// use spread operator in function call to
// turn array elements into function arguments
noMutate(…array);
console.log(array); // result [1, 2, 3, 4]

Передача других аргументов

Вы можете передавать другие аргументы с параметром rest, если они идут перед параметром rest. Например, вы можете реализовать собственную версию функции фильтра, которая умножает каждый элемент массива на другое число, например:

var arr = [1, 2, 3, 4];
const noMutate = (num, …arr) => {
 var multiple = []
 for(elem of arr) multiple.push(elem * num);
 return multiple;
}
var double = noMutate(2, …arr);
console.log(double); // returns [2, 4, 6, 8]
console.log(arr); // not mutated: [1, 2, 3, 4]

Вы даже можете использовать оператор распространения для передачи свойств объекта JavaScript, например:

var obj = {
 arr: [1, 2, 3, 4]
};
const noMutate = (num, …arr) => {
 console.log(arr);
 var multiple = []
 for(elem of arr) multiple.push(elem * num);
 return multiple;
}
var double = noMutate(2, …obj.arr);
console.log(double); // returns [2, 4, 6, 8]
console.log(arr); // not mutated: [1, 2, 3, 4]

Что касается производительности, я не уверен, как это можно сравнить с использованием Array.from() или .slice(), но это устраняет одну строку кода, и я думаю, что ваш код выглядит чище. Если кто-нибудь знает, как это влияет на производительность, пожалуйста, дайте мне знать.

Статья по теме: