Можно ли установить значение параметра по умолчанию для параметра покоя

ES6 представляет набор удобных "синтаксических сахара". Среди них - возможности параметров по умолчанию функций JavaScript, а также остальные параметры. Я обнаружил, что моя консоль (или devTools) жалуется (то есть выдает ошибку) всякий раз, когда пытается установить значение параметра по умолчанию для параметра rest. Я нашел удивительно мало ссылок на этот конкретный вопрос в другом месте, и мне интересно, если 1.) возможно ли это сделать и 2.) почему нет (при условии, что это невозможно).

В качестве примера я придумал тривиальный (но, надеюсь, все еще целеустремленный) пример. В этой первой итерации функции я построил функцию так, чтобы она работала (то есть, не давая параметру rest значение по умолчанию).

const describePerson = (name, ...traits) => `Hi, ${name}! You are ${traits.join(', ')}`;

describePerson('John Doe', 'the prototypical placeholder person');
// => "Hi, John Doe! You are the prototypical placeholder person"

Однако теперь по умолчанию:

const describePerson = (name, ...traits = ['a nondescript individual']) => `Hi, ${name}! You are ${traits.join(', ')}`;

describePerson('John Doe');
// => Uncaught SyntaxError: Unexpected token =

Любая помощь с благодарностью.

3 ответа

Решение

Нет, остальные параметры не могут иметь инициализатор по умолчанию. Это не разрешено грамматикой, потому что инициализатор никогда не будет запущен - параметру всегда присваивается значение массива (но, возможно, пустое).

То, что вы хотите сделать, может быть достигнуто либо

function describePerson(name, ...traits) {
     if (traits.length == 0) traits[0] = 'a nondescript individual';
     return `Hi, ${name}! You are ${traits.join(', ')}`;
}

или же

function describePerson(name, firstTrait = 'a nondescript individual', ...traits) {
     traits.unshift(firstTrait);
     return `Hi, ${name}! You are ${traits.join(', ')}`;
}

// the same thing with spread syntax:
const describePerson = (name, firstTrait = 'a nondescript individual', ...otherTraits) =>
    `Hi, ${name}! You are ${[firstTrait, ...otherTraits].join(', ')}`

Просто пришло добавить более чистую систему настроек по умолчанию:

const describePerson = (name, ...traits) => {
  traits = Object.assign(['x', 'y'], traits);

  return `Hi, ${name}, you are ${traits.join(', ')}`;
}

describePerson('z'); // you are z, y
describePerson('a', 'b', 'c'); // you are a, b, c
describePerson(); // you are x, y

Это работает, потому что массивы - это объекты, индексы которых являются ключами, а Object.assign заменяет ключи первого объекта, присутствующего во втором, значениями второго.

Если у второго нет индекса 1, он не будет перезаписан, но если у него есть индекс 0, индекс 0 первого массива будет перезаписан вторым, что вы ожидаете при использовании по умолчанию

Обратите внимание, что распространение массивов - это не то же самое, что распространение объектов, поэтому [....['x', 'y'], ...traits] не будет перезаписывать индексы

Есть решение:

      const describePerson = (name, ...[
  first = 'a nondescript individual',
  ...traits
]) => `Hi, ${name}! You are ${[first, ...traits].join(', ')}`;
Другие вопросы по тегам