# 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";
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://strctr.gitbook.io/programming/01-languages/javascript/01-language/c-functions/c1-functions/02.i-function-paramenters-es6.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
