Create a gist now

Instantly share code, notes, and snippets.

Several demos and usages for ES6 destructuring. Runnable demos and slides about the same topic: http://git.mikaelb.net/presentations/bartjs/destructuring
// === Arrays
var [a, b] = [1, 2];
console.log(a, b);
//=> 1 2
// Use from functions, only select from pattern
var foo = () => [1, 2, 3];
var [a, b] = foo();
console.log(a, b);
// => 1 2
// Omit certain values
var [a, , b] = [1, 2, 3];
console.log(a, b);
// => 1 3
// Combine with spread/rest operator (accumulates the rest of the values)
var [a, ...b] = [1, 2, 3];
console.log(a, b);
// => 1 [ 2, 3 ]
// Fail-safe.
var [, , , a, b] = [1, 2, 3];
console.log(a, b);
// => undefined undefined
// Swap variables easily without temp
var a = 1, b = 2;
[b, a] = [a, b];
console.log(a, b);
// => 2 1
// Advance deep arrays
var [a, [b, [c, d]]] = [1, [2, [[[3, 4], 5], 6]]];
console.log("a:", a, "b:", b, "c:", c, "d:", d);
// => a: 1 b: 2 c: [ [ 3, 4 ], 5 ] d: 6
// === Objects
var {user: x} = {user: 5};
console.log(x);
// => 5
// Fail-safe
var {user: x} = {user2: 5};
console.log(x);
// => undefined
// More values
var {prop: x, prop2: y} = {prop: 5, prop2: 10};
console.log(x, y);
// => 5 10
// Short-hand syntax
var { prop, prop2} = {prop: 5, prop2: 10};
console.log(prop, prop2);
// => 5 10
// Equal to:
var { prop: prop, prop2: prop2} = {prop: 5, prop2: 10};
console.log(prop, prop2);
// => 5 10
// Oops: This doesn't work:
var a, b;
{ a, b } = {a: 1, b: 2};
// But this does work
var a, b;
({ a, b } = {a: 1, b: 2});
console.log(a, b);
// => 1 2
// This due to the grammar in JS.
// Starting with { implies a block scope, not an object literal.
// () converts to an expression.
// From Harmony Wiki:
// Note that object literals cannot appear in
// statement positions, so a plain object
// destructuring assignment statement
// { x } = y must be parenthesized either
// as ({ x } = y) or ({ x }) = y.
// Combine objects and arrays
var {prop: x, prop2: [, y]} = {prop: 5, prop2: [10, 100]};
console.log(x, y);
// => 5 100
// Deep objects
var {
prop: x,
prop2: {
prop2: {
nested: [ , , b]
}
}
} = { prop: "Hello", prop2: { prop2: { nested: ["a", "b", "c"]}}};
console.log(x, b);
// => Hello c
// === Combining all to make fun happen
// All well and good, can we do more? Yes!
// Using as method parameters
var foo = function ({prop: x}) {
console.log(x);
};
foo({invalid: 1});
foo({prop: 1});
// => undefined
// => 1
// Can also use with the advanced example
var foo = function ({
prop: x,
prop2: {
prop2: {
nested: b
}
}
}) {
console.log(x, ...b);
};
foo({ prop: "Hello", prop2: { prop2: { nested: ["a", "b", "c"]}}});
// => Hello a b c
// In combination with other ES2015 features.
// Computed property names
const name = 'fieldName';
const computedObject = { [name]: name }; // (where object is { 'fieldName': 'fieldName' })
const { [name]: nameValue } = computedObject;
console.log(nameValue)
// => fieldName
// Rest and defaults
var ajax = function ({ url = "localhost", port: p = 80}, ...data) {
console.log("Url:", url, "Port:", p, "Rest:", data);
};
ajax({ url: "someHost" }, "additional", "data", "hello");
// => Url: someHost Port: 80 Rest: [ 'additional', 'data', 'hello' ]
ajax({ }, "additional", "data", "hello");
// => Url: localhost Port: 80 Rest: [ 'additional', 'data', 'hello' ]
ajax({ });
// => Url: localhost Port: 80 Rest: []
// Doesn't work due to trying to destructure undefined
ajax();
// => Uncaught TypeError: Cannot match against 'undefined' or 'null'
// To fix this we need to have default value for parameter in function
// Note: See the `= {}` at the end, saying default empty object if the first argument is undefined.
var ajax = ({ url: url = "localhost", port: p = 80} = {}) => {
console.log("Url:", url, "Port:", p);
};
// Now this works.
ajax();
// => Url: localhost Port: 80
ajax({ });
// => Url: localhost Port: 80
ajax({ port: 8080 });
// => Url: localhost Port: 8080
ajax({ url: "someHost", port: 8080 });
// => Url: someHost Port: 8080
// Like _.pluck
var users = [
{ user: "Name1" },
{ user: "Name2" },
{ user: "Name2" },
{ user: "Name3" }
];
var names = users.map( ({ user }) => user );
console.log(names);
// => [ 'Name1', 'Name2', 'Name2', 'Name3' ]
// Usage in for..of loops
var users = [
{ user: "Name1" },
{ user: "Name2", age: 2 },
{ user: "Name2" },
{ user: "Name3", age: 4 }
];
for (let { user, age = "DEFAULT AGE" } of users) {
console.log(user, age);
}
// => Name1 DEFAULT AGE
// => Name2 2
// => Name2 DEFAULT AGE
// => Name3 4
@weslleyaraujo

awesome examples!
really useful feature...

@cvasani
cvasani commented Dec 29, 2015

Thanks ..

@AshCoolman

Nice.

That js grammar issue is easy to explain with arrow functions:

var getUtils = () => {Math, window, document} // err...what? ok.
var getUtils = () => ({Math, window, document}) // oh, I get you
@shuaibird

awesome.
Thx

@mikaelbr
Owner
mikaelbr commented Apr 6, 2016

Here are slides with runnable demos and edit features from the talk where these examples originated: http://git.mikaelb.net/presentations/bartjs/destructuring

@gilesbradshaw
gilesbradshaw commented Jun 21, 2016 edited

How about

const name = "fieldName"
const {[name]: nameValue} = {fieldName: 'value'}

console.log(nameValue)
// => value
@mikaelbr
Owner
mikaelbr commented Jul 8, 2016

@gilesbradshaw Ah, a combination of variable property name and destructuring. I like that. Never thought of combining it. Adding it now 👍

@gilesbradshaw

glad you like it :)

@brunolemos

Manual pull request: Use Arrow Function Shorthand:

-var foo = () => {
-  return [1, 2, 3];
-};
+var foo = () => [1, 2, 3];
@mikaelbr
Owner

Updated. Didn't really have to be a fat arrow in that case, but just as well. 👍

@sabithpocker
sabithpocker commented Sep 22, 2016 edited

Good read. :)

[
  { firstName: "Paul", lastName: "Nicklen", age: 48, profession: "Photography"},
  { firstName: "Steve", lastName: "McCurry", age: 66, profession: "Photography"},
  { firstName: "Frans", lastName: "Lanting", age: 65, profession: "Photography"},
  { firstName: "Jimmy", lastName: "Chinn", age: 42, profession: "Photography"}
].map(({firstName, lastName, age}) => ({name:firstName + lastName, age}));
@jstewart8053

Super Helpful! Thanks!

@xgqfrms-GitHub

great work!

@iczechowski

You may also want to demonstrate destructuring with default function parameters.

var ajax = ({ url: url = "localhost", port: p = 80} = {}) => {
  console.log("Url:", url, "Port:", p);
}; 

ajax();
//  => Url: localhost Port: 80
 
ajax({ port: 8080 });
//  => Url: localhost Port: 8080

ajax({ url: "someHost", port: 8080 });
//  => Url: someHost Port: 8080
@mikaelbr
Owner
mikaelbr commented Nov 8, 2016

@iczechowski I updated the destructure function parameter section now to be more clear. Thanks!

@ariel2023

Hi @mikaelbr can I ask something?
I tried example
var {prop: x, prop2: [, y]} = {prop: 5, prop2: [10, 100]};
and when I print prop2 I get 10 instead of 100. Can you explain me why ? It shouldn't be [100] (an array containing number 100)? Since we ignore the 1st number.

Thank you in advance

@ariel2023

Additionally in the last example
[for ({ user, age = "DEFAULT AGE" } of users) console.log(user, age)];
I don't understand why we need the brackets [].

I tried it without brackets and works fine

@mikaelbr
Owner

Hi @ariel2023. Sorry for the late response, but I don't get notifications from gists. I don't understand what you mean about the first example you get:

var { prop: x, prop2: [, y] } = { prop: 5, prop2: [10, 100] };

Here you do "name prop x" and "name the second element of prop2 y", and if you try that in e.g. Chrome you do in fact get x = 5 and y = 100 as expected. Try running

var { prop: x, prop2: [, y] } = { prop: 5, prop2: [10, 100]};
console.log({ x, y });
//=> Result: Object {x: 5, y: 100}

As for the second example, this can probably removed. The example was written at a time where list comprehensions still was thought to be included in the new standard. Now we know it wasn't and is probably not getting included anytime soon. We have other patterns, such as map, reduce etc which can achieve much of the same, depending on usage.

So writing the example using those constructs instead we could do:

var users = [
  { user: "Name1" },
  { user: "Name2", age: 2 },
  { user: "Name2" },
  { user: "Name3", age: 4 }
];
users.forEach(({ user, age = "DEFAULT AGE" }) => console.log(user, age));

As a sidenote: It works when you remove the [] more as a happy accident, because that is valid syntax for a for..of loop.

for ({ user, age = "DEFAULT AGE" } of users) console.log(user, age);

becomes

for ({ user, age = "DEFAULT AGE" } of users) {
  console.log(user, age);
}

Which is destructuring user, age from users each iteration and printing that. Please note, though, this wouldn't work in strict mode. As we are not declaring our variables before using them in the destructuring. For it to be valid we would have to do something like:

for (let { user, age = "DEFAULT AGE" } of users) {
  console.log(user, age);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment