Can I pre-declare variables for destructuring assignment of objects?

Lucy Bain picture Lucy Bain · Jan 17, 2016 · Viewed 7k times · Source

Background

When I tried destructuring assignment with arrays I was able to pre-declare my variables:

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

This went through the Babel compiler just fine.

However when I tried to do the same with objects I got an error

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'

Question

Is this an ES6 or Babel quirk/problem? If it's intentional for ES6, why the difference from the way arrays are treated?

Note

I understand that replacing var with let means I'm not required to pre-declare my variables and that having the let inline is valid (and, I believe, generally prefered). I'd like to know about the difference between implementations rather than a "don't do it like that at all" answer.

Answer

thefourtheye picture thefourtheye · Jan 17, 2016

When you are destructuring an Object,

  1. you need to use the same variable names as the keys in the object. Only then you will get one to one correspondence and the values will be destructured properly.

  2. and you need to wrap the entire assignment in parenthesis if you are not using declaration statement, otherwise the object literal in the left hand side expression would be considered as a block and you will get syntax error.


So your fixed code would look like this

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

which is equivalent to

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