деструктуризация объекта без var

102

Почему деструктуризация объекта вызывает ошибку, если varперед ним нет ключевого слова?

{a, b} = {a: 1, b: 2};

бросает SyntaxError: expected expression, got '='

Следующие три примера работают без проблем

var {a, b} = {a: 1, b: 2};
var [c, d] = [1, 2];
    [e, f] = [1, 2];

Дополнительный вопрос: почему нам не нужен varдля деструктуризации массива?

Я столкнулся с проблемой, делая что-то вроде

function () {
  var {a, b} = objectReturningFunction();

  // Now a and b are local variables in the function, right?
  // So why can't I assign values to them?

  {a, b} = objectReturningFunction();
}
алават
источник

Ответы:

162

Проблема возникает из-за того, что {...}операторы имеют несколько значений в JavaScript.

Когда {появляется в начале утверждения , он всегда представляет блок , которому нельзя назначить. Если он появится позже в Заявлении как выражение , то он будет представлять объект.

varПомогает сделать это различие, поскольку он не может следовать заявление , как будет группировка скобка :

( {a, b} = objectReturningFunction() );

Из их документов: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Assignment_without_declaration

Примечания: круглые скобки (...) вокруг оператора присваивания необходимы при использовании деструктурирующего присваивания литерала объекта без объявления.

{a, b} = {a: 1, b: 2} не является допустимым автономным синтаксисом, так как {a, b} слева считается блоком, а не литералом объекта.

Однако ({a, b} = {a: 1, b: 2}) допустимо, как и var {a, b} = {a: 1, b: 2}

Перед вашим (...) выражением должна стоять точка с запятой, иначе оно может использоваться для выполнения функции в предыдущей строке.

Джонатан Лоновски
источник
Если он появится позже в Заявлении как выражение, то он будет представлять объект. Означает ли это, что у нас никогда не может быть области видимости блока внутри скобок группировки
sharad_kalya
Кончик группирующих скобок - отличный вариант.
Джеймс Смит
Это блестяще неясное знание, которое поставило меня в тупик. Он позволяет деструктурировать по всему объему (ну, вроде - вам, конечно, все равно нужно объявлять свои переменные). Но он устраняет ограничение на использование цепочек обещаний при необходимости использования нескольких переменных, разрешенных на одном этапе цепочки обещаний, на другом, без создания слишком большого количества беспорядка. Спасибо.
Кевин Teljeur
26

Если вы пишете Javascript без точек с запятой , то синтаксис «присвоение без объявления» должен начинаться с точки с запятой, чтобы он работал предсказуемо.

let a, b

;({a, b} = objectReturningFunction()) // <-- note the preceding ;

Просто хотел подчеркнуть это, поскольку это меня поймало, и, надеюсь, поможет другим сэкономить время, выясняя, почему это не работает и / или дает странные результаты с такими программами форматирования кода, как prettier.

В самом деле, это действительно прямо в принятом ответе (последняя строка процитированных документов), но его легко пропустить, особенно не видя примера!

Давниквиль
источник
1
Да уж. Причина, по которой люди используют точку с запятой!
jfriend00
2

Вот еще один способ:

let {} = {a, b} = objectReturningFunction()

Плюсы:

  • Скобки не нужны
  • Точки с запятой не нужны
  • Дополнительное задание - это гарантированное бездействие (при условии, что не происходит никаких странностей)

Минусы:

  • Выглядит немного странно, хотя, на мой взгляд, не более странно, чем !(){...}() IIFE .
  • Может быть непонятно, почему это там. Он гарантированно сбивает людей с толку при первой встрече, поэтому я бы не советовал использовать его как разовое.
протон
источник
Кажется, что IIFE более сопоставимы с ;({ a, b })чем let {} = { ... }. Но неплохой трюк. :)
shuckster
@ proto-n, +1, очень умная идея. Как вы к этому пришли?
Pacerier