In this post I'm gonna talk about a feature that was added to JavaScript with ES2015: Destructuring
I'm also going to talk about features ES2015 added to the initializer notation also known as object or array literals, which are the other side of the story.
And I'm going into some features that aren't part of the ECMAScript standard (yet), but very high on the list of becoming one in the near future. Compilers like Babel already implementing them.
Destructuring
Destructuring is a way to declare new variables based on objects or arrays, they can often eliminate the need of a few variable indirection's.
Lets start with a simple example.
// Without destructuring you would write this:
const someObject = {head: "ok", value: 11};
if (someObject.head == "ok" && someObject.value > 10) doSomething();
// With destructuring you could write it like that:
const {head, value} = {head: "ok", value: 11};
if (head == "ok" && value > 10) doSomething();
To add more sense to this, lets imagine you got someObject
from a function:
const {head, value} = getSomeObject();
if (head == "ok" && value > 10) doSomething();
Or you get it as argument to a callback:
function (otherArgument, someObject, anotherArgument) {
const {head, value} = someObject;
if (head == "ok" && value > 10) doSomething();
}
Which can be simplified to:
function (otherArgument, {head, value}, anotherArgument) {
if (head == "ok" && value > 10) doSomething();
}
Destructuring also allows you to go deeper:
const { a: { b: { c } } } = { a: { b: { c: 10 } } };
alert(c);
And, as I mentioned, it also works with arrays:
const [firstElement, SecondElement] = [ 1, 2, 3 ];
alert(firstElement + SecondElement);
And as argument:
function ([first, second]) {
return first + second;
}
Swapping some elements without a proxy variable:
const a = 1;
const b = 2;
[b, a] = [a, b];
As you see, when using arrays you are free to use any identifier you want, when using objects, you have to use the right property identifier.
Arrays destructuring also has a rest syntax, which lets you extract some elements and create a new array with the remaining elements quickly.
const [stringWithOne, ...arrayWithTwoAndThree] = ["one", "two", "three"];
There is even a rest syntax for objects, which aren't part of ECMAScript yet, but available via compilers like Babel.
const {a, ...objWithBAndC} = {a: 10, b: 11, c: 12};
One nice thing about using it for function arguments is, you can use it with the default value feature. So you can extract the right values from an object or an array and set default values for them in one stroke:
// Before
function parse(a) {
const type = a.type || "default"
...
}
// After
function parse({type = "default"}) {
...
}
// More complex
function parse(a = 10, [first, second, ...rest], {b: {c: [deepFirst = 99]}}) {
return rest.map(function(x) {
return a * first * second * x + deepFirst;
})
}
There is also a rest syntax specifically for parameters, that can be used without objects or arrays. It works as an arguments
replacement and is a real array.
function (a, b, ...otherArgs) {
...
}
Initializer Notation
The other side of this is the initializer notation, often also known as object literal syntax, which got a bit tweaked.
So you got your data extracted from somewhere and now you want to create a new object out of this.
// Before
const a = 10;
const b = 11;
const myObject = {a: a, b: b};
// After
const a = 10;
const b = 11;
const myObject = {a, b};
// Like it worked with arrays before:
const myArray = [a, b];
You can also use values of variables as names for your object inside the literal now:
// Before
const key = "hello";
const value = "world";
const newObject = {};
newObject[key] = value;
// After
const key = "hello";
const value = "world";
const newObject = {
};
// With some computation
const newObject = {
}
There is also an inversion of the rest syntax for objects. The spread operator, which isn't part of ECMAScript yet. It allows you to create new objects on the fly.
const props = {size: 10, color: "red"};
const newProps = {...props, color: "green", weight: 100};
With this you create objects based on other objects and can add properties (like weight
), or override properties of the base object (like color
).
But a bit of caution is advised. You get a new object, but if you got some indirection's in the base object (nested objects) these won't get cloned.