Tricks with JavaScript Destructuring

Parker McMullin

In order to understand the newer destructuring syntax introduced in ES6, let’s cover the “old” way. I’ll mention this a couple times throughout, but these are optional syntaxes that MAY help. There are still some use cases that are cleaner with the original methods, such as property accessors, and that is perfectly valid.

// some object
const apple = {
  numberOfLeaves: 2,
  colors: {
    actual: ['green', 'yellow'],
    possible: ['red', 'green', 'yellow'],
  },
  kind: 'Golden Delicious',
  sku: 'A-GD-01',
};

Here is how we might get values from this object before ES6:

// property accessors using the dot syntax
const kind = apple.kind;
const sku = apple.sku;

And now that we have destructuring, we can do something like this to extract both of these properties from the object and assign them to new const variables:

const { kind, sku } = apple;

It comes in handy for accessing nested values. You can also choose your own name for the variable - it doesn’t have to match the property name!

// instead of:
//   const colors = apple.colors.actual;
//   const possibleColors = apple.colors.possible;

const { actual: colors, possible: possibleColors } = apple.colors;

console.log(colors); // outputs ["green", "yellow"]
console.log(possibleColors); // outputs ["red", "green", "yellow"]

Array Destructuring

Array destructuring is very similar, and allows us to grab only some of the values from an array, like so:

const names = ['Jack', 'Janet', 'John', 'Jessie', 'Jaqueline', 'Jerry', 'Justin', 'Julie', 'Jake'];

const [first, second, third, ...theRest] = names;

console.log(first); // outputs "Jack"

console.log(theRest); // outputs ["Jessie", "Jaqueline", "Jerry", "Justin", "Julie", "Jake"]

As you can see, we are extracting the first 3 items into their own variables, and using the rest syntax ... to assign the remaining values into another new variable.

We do not have to assign the remaining values to a variable. Let’s say we only want the first array value - we can just enclose the variable in brackets.

Now, we’re going to combine the array destructuring with object destructuring to pull out the one value we want, reducing the extraction into one statement.

const winners = [
  { name: 'Mario',   time: 110 },
  { name: 'Waluigi', time: 115 },
  { name: 'Toad',    time: 116 },
  { name: 'Yoshi',   time: 124 },
  { name: 'Bowser',  time: 129 },
];

function getBestTimeOf(racers) {
  // extract only the first item and from that, we only assign 
  // the property of time to the new variable of bestTime
  const [{ time: bestTime }] = racers;
  return bestTime;
}

console.log( getBestTimeOf(winners) ); // outputs 110

Some may not think that this extraction is cleaner than const bestTime = winners[0].time; and I agree that we may lose some ability to quickly read the code. That is why every strategy requires foresight and common sense before implementing it. In your real-life examples, you will likely be pulling more than just ONE property from ONE array value. Destructuring will greatly help at that point.

Two more quick tips for arrays

  1. You can swap values, assuming that they are not defined with const.
let a = 2;
let b = 5;

[a, b] = [b, a];
console.log(a); // 5
console.log(b); // 2
  1. You may skip values by leaving the slot with a comma. In this example, I’ll pull only the second value. Don’t worry about the regular expression usage - I have altered the code slightly from a project of mine in order to show a possible usage.
const [,, three] = [1, 2, 3, 4, 5, 6, 7];
console.log(`I selected ${three}.`); // outputs "I selected 3."

🔥🔥 Hot Tips for Functions 🔥🔥

Multiple Return Values

You can use array destructuring to cleanly return multiple values from a function! React devs using the new hooks functionality may be familiar with how this is used:

const [count, setCount] = useState(0);

All you need to do to have the same functionality of returning multiple values is to return those values. Literally.

function getCoordinates(address) {
  // use an API to get the lon/lat of an address
  const coordinates = maps.address(address).coordinates;
  return [coordinates.lon, coordinates.lat];
}

// later I can get this with
const [longitude, latitude] = getCoordinates(someAddress);

Expressive Parameter / Argument Syntax

This is by far my favorite usage of destructuring. We are going to use objects as both our function parameters AND arguments! This can greatly simplify the structure of functions. Just as a reminder, you do not need to use this in every case, such as for those that are already straightforward.

To clarify — A parameter is a variable in a function declaration. An argument is the data you pass into the function parameters when it is called.

Below is a snippet to clarify these definitions. Don’t pay too much attention to what the code is doing - look to see what the notes are pointing out.

// level and data are the parameters
function logData(level, data) {
  console.log(`New log of level: ${level}`);
  console.log(data);
}

const someLevel = 'error';
const calculatedData = {
  id: 1,
  name: 'Jack',
};

// the VALUES of someLevel and calculatedData are the arguments 
// we are passing to logData() - the variable names are irrelevant
logData(someLevel, calculatedData);

Here is some code which could controls part of a telecommunications switch. This function sets a variable on a call channel. Again, disregard the actual code purpose and focus on the notes and strategy.

// ...inside a class
async set({
  variable = '',
  value = '',
  callId = '',
} = {})
{
  console.log(`Setting ${variable} equal to ${value} on call ID: ${callId}`);
  return await this.api('call_setvar', `${callId} ${variable} ${value}`);
}

I call this function like:

// callId and url are defined above

await this.set({ callId, variable: 'custom_transfer_url', value: url });

This method of passing-in an object and having it be implicitly destructured on the other end lends us some valuable benefits:

  1. named parameters (self-documenting)
  2. default values (via the = sign) **
  3. order is inconsequential
  4. object property-value shorthand (use the same name for property and variable that holds the value, such as for how uuid is passed in) uuid: uuid, was shortened to uuid,

You do not have to put each variable on a different line as you see in my function declaration. I do this so that I can cleanly provide defaults and notes if I choose to.

** Note that default values will only be used if the value is undefined, meaning that it was not passed-in or it was explicitly set to undefined. Null values will not trigger the default and will remain null.

I hope that these uses of array and object destructuring have given you some new ways to simplify and structure your code! If you think any of your fellow developers could use these tips, please share this with them. You can also tweet or share this and link to @alligatorio!

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#