Dominic Myers, a senior UX developer at Arcus Global, gives a brief introduction to destructing in ES6.

I’ve been doing loads of stuff with HTML Canvas recently and one thing that has really annoyed me is sorting out variables.

Say I’m drawing rectangles on the Canvas using the mouse. I need to listen to a mouse click event and, if my x and y variables are undefined, set them to the mouse’s x and y coordinates. When I’m moving my mouse I need to show where the current rectangle is, to give some sort of visual reference, so I need to have the width and height of the rectangle as fillRect takes these as parameters. When I lift the mouse I need to save the rectangle to an array of rectangle objects with each having an x, y, width and height. This needs to occur as, when I interact with the canvas in a meaningful way, I need to redraw the canvas. This JSFiddle shows what I mean.

So this works:

rectangles.push({
    x: x,
    y: y,
    width: width,
    height: height
});
 

But the thing I’ve always been annoyed with, and this might be a very small thing, is the code required to push the new rectangle to the rectangles array. I have to re-type x, y, width and height. It might not be a big thing in this context, but if my objects are bigger then it gets boring really quickly, especially if I’ve been odd with my variable naming (and I generally am). It turns out that one of the benefits of ES6 destructuring is that I no longer have to do this, this code works well and is arguably easier to read:

rectangles.push({x, y, width, height});
 

This JSFiddle illustrates this destructuring at work. The keen-eyed amongst you might also notice that the drawing of existing rectangles within the redraw function has changed as well. I’ve used the Object.values() method to return the values of the rectangle object as an array and then used the spread syntax to expand the array of values to get the x, y, width and height variables.

The need for messing around awith Object.values() and the spread syntax can be removed as destructuring will work here as well:

const {x, y, width, height} = rectangle;
context.fillRect(x, y, width, height);

Here we’re saying that our x, y, width and height variables are being taken from the rectangle object (we know they’re coming from an object because of the curly brackets). This is illustrated in this JSFiddle.

If I had decided to populate my rectangles array with arrays, such that the code below represents two existing rectangles. I could have destructured it like this:

let rectanglesArray = [[20, 20, 50, 10], [30, 30, 10, 20]];
if (rectanglesArray.length) {
    rectanglesArray.forEach((rectangle) => {
        const [x, y, width, height] = rectangle;
        context.fillRect(x, y, width, height);
    });
}
 

The thing to take away from this is the square brackets around the x, y, width and height variables: because we’re taking from an array rather than an object we define our variables differently. Of course, this might have been a better way of writing this code:

context.fillRect(...rectangle);

 

I have only dipped my toes into destructuring in this article and I suggest you read up on what you can accomplish with it, if nothing else you’ll save yourself an awful lot of typing. Happy coding.