02.i ES6 Parameters

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

  • default parameter values

  • rest parameters (varargs)

  • deconstructing on parameters

  • spread arguments

Default Parameters

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

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

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

Синтаксис ES6:

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

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

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

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

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

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

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

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

...rest parameters

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

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

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

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

Destruction in Parameters

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

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):

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 подобную логику можно упростить при помощи деструкции параметров вместе со значениями по умолчанию:

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

spread operator

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

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

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

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

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

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

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

// strings
return Math.max(..."1234") === 4;
  • В массивах:

// 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']
  • Преобразование любой итерируемой сущности в массив:

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]
  • При генераторе

// 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";

Last updated