Начиная с ECMAScript 6 появилась возможность использовать параметры по умолчанию и остаточные параметры у функций.
Зачастую функции не нужно, чтобы все её параметры передавались ей явным образом, и
есть какие-то значения по умолчанию, которые используются вместо тех параметров,
которые не были переданы. В JavaScript всегда существовала не очень гибкая разновидность
параметров по умолчанию — параметры, для которых значение не передано, равны undefined
.
В ECMAScript 6 появилась возможность задавать для параметров функции произвольные значения
по умолчанию.
// ECMAScript 5
function greet(name) {
if (!name) {
return `Hello, guest.`;
}
return `Hello, ${name}.`;
}
console.log(greet());
// Ожидаемый результат: "Hello, guest."
console.log(greet('John'));
// Ожидаемый результат: "Hello, John."
console.log(greet(undefined));
// Ожидаемый результат: "Hello, guest."
Если в качестве одного из аргументов не было передано значение, то можно задать значение по умолчанию у данного аргумента. Это позволяет избавиться от проверок внутри функции.
// ECMAScript 6
function greet(name = 'guest') {
return `Hello, ${name}.`;
}
console.log(greet());
// Ожидаемый результат: "Hello, guest."
console.log(greet('John'));
// Ожидаемый результат: "Hello, John."
console.log(greet(undefined));
// Ожидаемый результат: "Hello, guest."
Существует несколько особенностей, связанных с параметрами по умолчанию:
- В отличие от других языков программирования, например, Python, выражения для определения значений по умолчанию вычисляются в момент вызовы функции, слева направо. Это означает, что такие выражения могут использовать значения из параметров, заполненных перед ними;
- Если функции передано
undefined
, то это считается эквивалентным тому, что вообще ничего не передано; - У параметра, для которого не указано значение по умолчанию, оно неявно равно
undefined
.
При создании API часто приходится писать вариадические1 функции. К примеру, метод
String#concat
может принимать любое количество строковых аргументов.
ECMAScript 6 предоставляет новый способ писать вариадические функции: при помощи
остаточных параметров.
// ECMAScript 5
var array = [];
function containsAll(arr) {
for (var i = 0; i < arguments.length; i++) {
var value = arguments[i];
if (arr.indexOf(value) === -1) {
return false;
}
}
return true;
}
В такой реализации используется объект arguments
— массивоподобный объект (т.н. «псевдомассив»),
содержащий все параметры, переданные функции. Этот код определённо делает то, что
нужно, но его читаемость оставляет желать лучшего.
В сигнатуре функции указан только один параметр, arr
, поэтому с первого
взгляда непонятно, что эта функция на самом деле может принимать сколько угодно аргументов.
Вдобавок следует быть осторожными и не забывать, что начинать перебирать arguments
следует со смещения 1, а не 0, потому что arguments[0]
соответствует объявленному
параметру arr
. Если когда-нибудь потребуется добавить ещё один параметр перед или после
arr
, нужно будет обновить цикл for
.
Остаточные параметры призваны обходить оба этих затруднения. Вот как выглядит
реализация этой же функции на ECMAScript 6, с использованием остаточного параметра:
// ECMAScript 6
const array = [];
function containsAll(arr, ...values) {
for (let value of values) {
if (!arr.includes(value)) return false;
}
return true;
}
Многоточие перед values
означает, что это остаточный параметр. Все остальные
переданные параметры собираются в массив, и кладутся в аргумент values
. Далее
выполнение функции продолжается как обычно.
Только последний параметр функции может быть помечен как остаточный. При вызове
параметры функции перед остаточным параметром заполняются как обычно. Все
«дополнительные» аргументы помещаются в массив и присваиваются
остаточному параметру. Если дополнительных аргументов нет, остаточный параметр будет
просто пустым массивом, он никогда не может быть равным undefined
.
// ECMAScript 6
function sum(...values) {
return values.reduce((acc, item) => acc + item, 0);
}
console.log(sum(1, 2, 3, 4, 5));
// Ожидаемый результат: 15
Вариадическая функция1 — функция, принимающая любое количество аргументов.