JavaScript. Остаточные параметры и оператор расширения
28.05.2021
Теги: JavaScript • Web-разработка • Параметр • Теория • Функция
Остаточные параметры (rest)
Вызывать функцию можно с любым количеством аргументов независимо от того, как она была определена. Лишние аргументы при вызове не вызовут ошибку, просто функция в работе использует не все аргументы.
function sum(a, b) { return a + b; } alert( sum(1, 2, 3, 4, 5) );
Остаточные параметры могут быть обозначены через три точки ...
. Буквально это значит: «собери оставшиеся параметры и положи их в массив».
function sumAll(...args) { // args — имя массива let sum = 0; for (let arg of args) { sum = sum + arg; } return sum; } alert( sumAll(1) ); // 1 alert( sumAll(1, 2) ); // 3 alert( sumAll(1, 2, 3) ); // 6
В примере ниже первые два аргумента функции станут именем и фамилией, а третий и последующие превратятся в массив others
:
function showName(firstName, lastName, ...others) { alert( firstName + ' ' + lastName ); // Сергей Иванов // Оставшиеся параметры пойдут в массив // others = ['Россия', 'Москва'] alert( others[0] ); // Россия alert( others[1] ); // Москва alert( others.length ); // 2 } showName('Сергей', 'Иванов', 'Россия', 'Москва');
Переменная arguments
Все аргументы функции находятся в псевдомассиве arguments
под своими порядковыми номерами.
function showName() { alert( arguments.length ); alert( arguments[0] ); alert( arguments[1] ); // Объект arguments можно перебирать // for (let arg of arguments) alert(arg); } // Вывод: 2, Сергей, Иванов showName('Сергей', 'Иванов'); // Вывод: 1, Андрей, undefined (второго аргумента нет) showName('Андрей');
Раньше в javascript не было остаточных параметров, и получить все аргументы функции можно было только с помощью arguments
. Этот способ всё ещё работает, его можно встретить в старом коде.
Но у него есть один недостаток. Хотя arguments
похож на массив, и его тоже можно перебирать, это всё же не массив. Он не поддерживает методы массивов, поэтому нельзя вызвать, например, arguments.map(...)
.
К тому же, arguments
всегда содержит все аргументы функции — нет возможности получить их часть. А остаточные параметры позволяют это сделать. Соответственно, для более удобной работы с аргументами лучше использовать остаточные параметры.
Оператор расширения (spread)
Например, есть встроенная функция Math.max()
. Она возвращает наибольшее число из списка:
alert( Math.max(3, 5, 1) ); // 5
Допустим, у нас есть массив чисел [3, 5, 1]
. Как вызвать для него Math.max()
? Просто так их не вставишь — Math.max()
ожидает получить список чисел, а не один массив.
let arr = [3, 5, 1]; alert( Math.max(arr) ); // NaN
Тут на помощь приходит оператор расширения. Он похож на остаточные параметры — тоже использует ...
, но делает совершенно противоположное. Когда ...arr
используется при вызове функции, он «расширяет» перебираемый объект arr
в список аргументов.
let arr = [3, 5, 1]; alert( Math.max(...arr) ); // 5
Этим же способом можно передать несколько итерируемых объектов:
let arr1 = [1, -2, 3, 4]; let arr2 = [8, 3, -8, 1]; alert( Math.max(...arr1, ...arr2) ); // 8
Можно даже комбинировать оператор расширения с обычными значениями:
let arr1 = [1, -2, 3, 4]; let arr2 = [8, 3, -8, 1]; alert( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25
Оператор расширения можно использовать и для слияния массивов:
let arr = [3, 5, 1]; let arr2 = [8, 9, 15]; let merged = [0, ...arr, 2, ...arr2]; alert(merged); // 0,3,5,1,2,8,9,15
В примерах выше мы использовали массив, чтобы продемонстрировать свойства оператора расширения, но он работает с любым перебираемым объектом. Например, чтобы превратить строку в массив символов:
let str = 'Привет'; alert( [...str] ); // П,р,и,в,е,т
Для этой задачи можно использовать и Array.from()
. Он тоже преобразует перебираемый объект (такой как строка) в массив:
let str = 'Привет'; alert( Array.from(str) ); // П,р,и,в,е,т
Но между Array.from(obj)
и [...obj]
есть разница:
Array.from()
работает как с псевдомассивами, так и с итерируемыми объектами- Оператор расширения работает только с итерируемыми объектами
Выходит, что если нужно сделать из чего угодно массив, то Array.from()
— более универсальный метод.
Spread в литералах объекта
Клонирование объекта с одновременным добавлением дополнительных свойств:
const user = {id: 100, name: 'Сергей Иванов'}; const userWithPass = {...user, password: 'qwerty'} console.log(userWithPass);
{id: 100, name: 'Сергей Иванов', password: 'qwerty'}
Объединяем два объекта part1
и part2
в новый объект user
:
const part1 = {id: 100, name: 'Сергей Иванов'} const part2 = {id: 100, password: 'qwerty'} const user = {...part1, ...part2} console.log(user);
{id: 100, name: 'Сергей Иванов', password: 'qwerty'}
Свойства объекта можно удалить с помощью деструктуризации и оператора rest
. Здесь мы исключаем password
, собираем оставшиеся свойства в объект rest
и возвращаем этот объект из стрелочной функции.
const noPassword = ({password, ...rest}) => rest const user = { id: 100, name: 'Сергей Иванов', password: 'qwerty' } const userNoPass = noPassword(user); console.log(userNoPass);
{id: 100, name: 'Сергей Иванов'}
Поиск: JavaScript • Web-разработка • Параметр • Теория • Функция • rest • spread