Могу ли я предварительно объявлять переменные для деструктурирования назначения объектов?

Фон

Когда я попытался выполнить деструктурирование задания с помощью массивов, я смог предварительно объявить свои переменные:

let a, b, c;
let arr = [1, 2, 3, 4, 5];
[a, b, c] = arr;

console.log(a) // logs 1
console.log(b) // logs 2
console.log(c) // logs 3

Это очень просто прошел через компилятор Babel.

Однако, когда я пытался сделать то же самое с объектами, я получил ошибку

let a, b, c
let obj = {cat: 'meow', dog: 'woof', mouse: 'squeak'};
{cat: a, dog: b, mouse: c} = obj;

console.log(a) // I want this to log 'meow'
console.log(b) // I want this to log 'woof'
console.log(c) // I want this to log 'squeak'

Вопрос

Является ли это причудой/проблемой для ES6 или Babel? Если это преднамеренно для ES6, то почему разница в том, как обрабатываются массивы?

Примечание

Я понимаю, что замена var на let означает, что мне не требуется предварительно объявлять мои переменные и что наличие встроенной строки let действительно (и, я считаю, в целом предпочтительнее). Я хотел бы узнать о различии между реализациями, а не об ответе "не делайте этого, как это вообще".

Ответ 1

Когда вы разрушаете объект,

  1. вам нужно использовать те же имена переменных, что и ключи в объекте. Только тогда вы получите однозначное соответствие, и значения будут должным образом деструктурированы.

  2. и вам нужно заключить все назначение в круглые скобки, если вы не используете оператор объявления, в противном случае литерал объекта в левом выражении будет рассматриваться как блок, и вы получите синтаксическую ошибку.


Так что ваш фиксированный код будет выглядеть так

'use strict';
let cat, dog, mouse;
let obj = {cat: 'meow', dog: 'woof', mouse: 'squeak'};
({cat, dog, mouse} = obj);     // Note the '()' around

что эквивалентно

'use strict';
let obj = {cat: 'meow', dog: 'woof', mouse: 'squeak'};
let {cat, dog, mouse} = obj;