> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/c-functions/c1-functions/02.i-function-paramenters-es6.md).

# 02.i ES6 Parameters

В ES6 работа с параметрами функции была существенно расширена:

* default parameter values
* rest parameters (`varargs`)
* deconstructing on parameters
* spread arguments

## Default Parameters

Параметр по умолчанию используется при отсутствующем параметре или равном `undefined`. При передаче любого значения, кроме `undefined`, включая пустую строку, ноль или `null`, параметр считается переданным, и значение по умолчанию не используется. *Параметры по умолчанию могут быть не только значениями, но и выражениями и вызовами функций.*

Традиционный прием для эмуляции параметров по умолчанию в ES5:

```javascript
function pair(x, y) {
  var x = x || 0;
  var y = y || 0;
  return [x, y];
}
```

Синтаксис ES6:

```javascript
function showMenu(title = "Без заголовка", width = 100, height = 200) {
  alert(`${title} ${width} ${height}`);
}

function sayHi(who = getCurrentUser().toUpperCase()) {
  alert(`Привет, ${who}!`);
}
```

Параметры могут ссылаться друг на друга в порядке своего объявления:

```javascript
function func(x = 1, y = x) {
  return [x, y];
}
```

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

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

```javascript
function mandatory() {
  throw new Error("Missing parameter");
}

function foo(mustBeProvided = mandatory()) {
  return mustBeProvided;
}
```

## `...rest` parameters

Оператор **rest** (`…`) оператор записывает все оставшиеся переданные аргументы функции в соответствующий массив, с методами `map`, `forEach` и другими, в отличие от `arguments`:

```javascript
return (function(foo, ...args) {
  return args instanceof Array && args + "" === "bar,baz";
})("foo", "bar", "baz");
```

Использование `rest` позволяет полностью заменить использование псевдо-массива `arguments`. Сочетая rest и деструктуризацию можно иметь как массив, так и отдельные параметры:

```javascript
function foo(...args) {
    const [x = 0, y = 0] = args;
    console.log('Arity: '+args.length);
    ···
}
```

## Destruction in Parameters

Если хочется, чтобы функция могла быть вызвана вообще без аргументов — нужно добавить ей параметр по умолчанию — уже не внутрь деструктуризации, а в самом списке аргументов:

```javascript
const options = {
  title: "Меню",
  width: 100,
  height: 200
};

function showMenu({ title, width, height }) {
  alert(`${title} ${width} ${height}`); // Меню 100 200
}

function showMenu({
  title = "Заголовок",
  width: w = 100,
  height: h = 200
} = {}) {
  alert(`${title} ${w} ${h}`);
}
showMenu(); // Заголовок 100 200
```

## Option Object (Named parameters)

Можно реализовывать именованные параметры через передачу объекта (*option object*):

```javascript
selectEntries({start: 3, end: 20, step: 2});
selectEntries({step: 2});
selectEntries({end: 20, start: 3});
selectEntries();

function selectEntries(options) {
    options = options || {};
    const start = options.start || 0;
    const end = options.end || getDbLength();
    const step = options.step || 1;
    ...
}
```

В ES6 подобную логику можно упростить при помощи деструкции параметров вместе со значениями по умолчанию:

```javascript
function selectEntries({start = 0, end = getDbLength(), step = 1}) {
    ...
}
```

## `spread` operator

Оператор `spread` применяется к любой итерируемой структуре и преобразует её в последовательность значений. Чаще всего используется при вызове функции для преобразования структуры в последовательность аргументов, передаваемых в функцию.

```javascript
> Math.max(-1, 5, 11, 3)
11
> Math.max(...[-1, 5, 11, 3])
11
> Math.max(-1, ...[-1, 5, 11], 3)
11
```

Части массива могут быть преобразованы в значения:

```javascript
> [1, ...[2,3], 4]
[1, 2, 3, 4]
```

Оператор `spread` выглядит так же как и оператор `rest` (`...`) но противоположен ему по смыслу. Оператор `rest` используется только внутри функции, тогда как оператор `spread` только при вызове функции или конструктора.

Вместо массива со `spread` можно использовать любые *итерируемые* структуры, такие как строки, генераторы, объекты (?).

* При строках:

```javascript
// strings
return Math.max(..."1234") === 4;
```

* В массивах:

```javascript
// strings
["a", ..."bcd", "e"][3] === "d";
const x = ["a", "b"];
const y = ["c"];
const z = ["d", "e"];
const arr = [...x, ...y, ...z]; // ['a', 'b', 'c', 'd', 'e']
```

* Преобразование любой итерируемой сущности в массив:

```javascript
const map0 = new Map([
  [1, "a"],
  [2, "b"],
  [3, "c"]
]);
// copy map
const map1 = new Map([...map0]);
// spread set into array
const set = new Set([11, -1, 6]);
const arr = [...set]; // [11, -1, 6]
```

* При генераторе

```javascript
// generator
const iterable = (function*() {
  yield 1;
  yield 2;
  yield 3;
})();

Math.max(...iterable) === 3;

// generators
const iterable = (function*() {
  yield "b";
  yield "c";
  yield "d";
})();
["a", ...iterable, "e"][3] === "d";
```
