Деструктурирование объекта без var, let или const

#javascript

#javascript #ecmascript-6

Вопрос:

Почему деструктурирование объекта выдает ошибку, если 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];
 

Бонусный вопрос: Почему нам не нужен a 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();
}
 

Ответ №1:

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

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

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

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

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

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

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

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

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

Комментарии:

1. Если оно появится позже в инструкции как выражение, то оно будет представлять объект. Означает ли это, что мы никогда не сможем иметь область действия блока внутри группирующей скобки

2. Отличный совет по группировке скобок.

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

Ответ №2:

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

 let a, b

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

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

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

Комментарии:

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

Ответ №3:

Вот другой способ:

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

Плюсы:

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

Минусы:

  • Выглядит немного странно, хотя, на мой взгляд, не более странно, чем !(){...}() IIFE.
  • Может сбивать с толку, почему это там. Это гарантированно сбивает людей с толку при первом столкновении, поэтому я бы не советовал использовать его как одноразовый.

Комментарии:

1. Похоже, что IIFE более сопоставимы с ;({ a, b }) than let {} = { ... } . Хороший трюк. 🙂

2. @proto-n, 1, очень умная идея. Как вы с этим столкнулись?

Ответ №4:

Рассмотрим:

 colors = { r: 204, g: 51, b: 102, hex: "#cc3366" };
 

Вот суть некоторых способов деструктурирования:

Деструктурирование в новые переменные

 let { r, g, b } = colors;
// initializes variables r, g, b
 

Деструктурирование в новые переменные с разными именами

 let { r: red, g: green, b: blue } = colors;
// initializes variables red, green, blue
 

Деструктурирование существующих переменных

 let r, g, b;
...
({ r, g, b } = colors);
 

Деструктурирование для существующих переменных с разными именами

 let red, green, blue;
...
({ r: red, g: green, b: blue } = colors);
 

Деструктурирование в другой объект с теми же именами свойств

 let myColor = { r: 0, g: 0, b: 0 };
...
({ r: myColor.r, g: myColor.g, b: myColor.b } = colors);
 

Деструктурирование в другой объект с другими именами свойств

 let myColor = { red: 0, green: 0, blue: 0 };
...
({ r: myColor.red, g: myColor.green, b: myColor.blue } = colors);