DEV Community

K
K

Posted on

JavaScript Destructs

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();
Enter fullscreen mode Exit fullscreen mode

To add more sense to this, lets imagine you got someObject from a function:

const {head, value} = getSomeObject();

if (head == "ok" && value > 10) doSomething();
Enter fullscreen mode Exit fullscreen mode

Or you get it as argument to a callback:

function (otherArgument, someObject, anotherArgument) {

  const {head, value} = someObject;

  if (head == "ok" && value > 10) doSomething();

}
Enter fullscreen mode Exit fullscreen mode

Which can be simplified to:

function (otherArgument, {head, value}, anotherArgument) {

  if (head == "ok" && value > 10) doSomething();

}
Enter fullscreen mode Exit fullscreen mode

Destructuring also allows you to go deeper:

const { a: { b: { c } } } = { a: { b: { c: 10 } } };

alert(c);
Enter fullscreen mode Exit fullscreen mode

And, as I mentioned, it also works with arrays:

const [firstElement, SecondElement] = [ 1, 2, 3 ];

alert(firstElement + SecondElement);
Enter fullscreen mode Exit fullscreen mode

And as argument:

function ([first, second]) {

  return first + second;

}
Enter fullscreen mode Exit fullscreen mode

Swapping some elements without a proxy variable:

const a = 1;
const b = 2;

[b, a] = [a, b];
Enter fullscreen mode Exit fullscreen mode

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"];
Enter fullscreen mode Exit fullscreen mode

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};
Enter fullscreen mode Exit fullscreen mode

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;
  })
}
Enter fullscreen mode Exit fullscreen mode

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) {
  ...
}
Enter fullscreen mode Exit fullscreen mode

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];
Enter fullscreen mode Exit fullscreen mode

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 = {

 }
Enter fullscreen mode Exit fullscreen mode

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};
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (2)

Collapse
 
strredwolf profile image
STrRedWolf

On other words, EMCA stole from Perl, stretched one idea out, and made another an explicit option.

my @list = ("A","B","C","D");  # Simple array
my ($a,$b,@rest) = @list;
print "$a and $b.\n";  # "A and B."
print (join " ", @rest),"\n";  # "C D"

my @longerlist = (@list,"E","F","G");  # Perl flattens out arrays.
my ($lla, @ll) = @longerlist;
print "$lla but not ",@ll,"\n"; # "A but not BCDEFG"
Enter fullscreen mode Exit fullscreen mode

The first example, I'm able to pull two values out and save the rest for later. This is used with subroutines in Perl, where options are put in a localized @_ array. With EMCAScript, that will need the "..." prefix to tell it explicitly to save the rest of the objects in the array/hash.

The second example makes use of Perl's "always flatten arrays" policy. EMCAScript will need the "..." prefix.

The only difference is that EMCAScript allows nesting. I think with Perl you will need to unroll each layer to get your variable.

Collapse
 
kayis profile image
K

Interesting. I never used Perl :)