APB: Demystified Destructuring
Tags: javascript, react, es6, destructuring
Published: 2020-12-21 00:22:07

I love digital media - blogs, e-books, the more the better. But as a self-identifying bibliophile, I never go long without picking up an old-school, paper and ink book. When I want to deeply learn something I always come back to the printed word. 
There's something about highlighting passages, and scribbling in the margins that cements information in my mind. I'm not alone in this, and there have been several [studies](https://hechingerreport.org/evidence-increases-for-reading-on-paper-instead-of-screens/) that suggest students of all ages learn more, and retain more of what they learn, from physical books. 

I'm currently working my way through the third edition of [Eloquent JavaScript](https://eloquentjavascript.net/) by Marijn Haverbeke. Though I consider JavaScript my primary language and felt comfortable with it before starting, I've learned something new, or gained a deeper understanding of something I already knew with every chapter. 

During my study time the other night I came to a section about the ES6 features we all know and love, specifically destructuring. The section was short, more of a summary than a deep dive, but it made me realize I needed to know more about this ES6 feature - so I added it to the All Points Bulletin Board.

---

### Question: What is Destructuring Assignment?
#### Short Answer: Destructuring is a succinct way to pull values out of an object and attach them to local variables in a single statement. It can be used on arrays or objects, allowing us to provide aliases, default values, and even complex expressions to obtain or replace data. 

--- 

#### The Long Answer 
The first time I saw destructuring was when learning React, and you'll see it in a lot of similar frameworks and libraries. It allows us to easily unpack multiple values from an array or object and assign them to variables in a single line.

Despite its name, destructuring isn't *destructive* - nothing is being destroyed. The original array is not mutated. Destructuring assignment allows us to literally *deconstruct* the object into its constituent parts, make copies and assign them to new local variables. 

The feature came about because we had ways to *construct* multiple properties at the same time through object and array literals, but no comparable mechanism of extracting data - other than piecemeal assignments. 

```jsx
const numbersArray = [1, 2]; 
const x = numbersArray[0]; 
const y = numbersArray[1];
console.log(x, y);
//---> 1, 2
```

Destructuring assignment works on the 2 most used data structures in JavaScript - arrays and objects. *Array destructuring* and *object destructuring* are very similar, with a few notable differences. We'll talk about array destructuring first. 

#### Array Destructuring
At first glance destructuring looks a lot like an array or object literal - but flipped. Instead of a variable declaration on the left with the assignment on the right - the extracted values appear to the left, and the sourced variable on the right. 

```jsx
const numbersArray = [1, 2]; // array literal
const [ x, y ] = numbersArray; // destructuring assignment
console.log(x, y);
//---> [1, 2] 
```

> Note: I've used a subtle naming convention in the code above. When I use destructuring I pad the variables in the destructuring array between brackets or braces with a leading and trailing space. This helps me read my code later, scanning files I can easily identify when I'm using destructuring assignment.

Arrays are obsessed with position, just take a look at their built-in methods, and how those methods traverse elements. Array destructuring is no different, as we saw in the example above. The variables we created were assigned their values after being mapped to the value at the same index in the sourced array. 

Using that syntax we know how to grab values from an array, but what else can we do? 

* **We can assign values after declaration**

```jsx
let [a, b]; 
[ a, b ] = ["dog", "cat"];
```

* **We can skip values** 

If the source variable contains values of no interest, they can be skipped with a comma and an empty space. 

```jsx
const dogs = ["Sparkles", "Rover", "Mosby", "Rufus"]; 
const [ a, , b, c ] = dogs;
const [ , , ,favorite ] = dogs;
console.log(a, b, c); 
//---> "Sparkles", "Mosby", "Rufus"
console.log(favorite);
//---> "Rufus"
```

* **We can manipulate values with array methods**

We can chain other methods that also return an array - like `.split`. 

```jsx
const name = "Mark Johnson"; 
const [ firstName, lastName ] = name.split(' '); 
console.log(firstName);
//---> "Mark"
```

* **We can provide default values**

What if we try to unpack more values than the sourced array contains? In that case those empty variables will return undefined, and no error will be thrown.

To avoid ambiguity, we can provide a default value using the assignment operator. 

```jsx
const employeeHours = [34, 40]; 
const [ employeeOne = 30, employeeTwo = 30, employeeThree = 30 ] = employeeHours; 
console.log(employeeThree);
//---> 30
console.log(employeeOne);
//---> 34
```

These default values can take on much more depth, becoming complex expressions or function calls. They will only be evaluated if a value cannot be found. 
Below I've used the `.reduce` method in a helper function to find the average of `employeeHours` and assigned it as a back-up for employeeThree. 

```jsx
const employeeHours = [34, 40]; 
const findAvg = (hours) => hours.reduce((a, b) => a + b, 0) / hours.length;
const [ employeeOne, employeeTwo, employeeThree = findAvg(employeeHours) ] = employeeHours; 
console.log(employeeThree);
//---> 37
```

* **We can assign the Rest** 

If we extract only one value from the sourced iterable, then we only get that single value. What if we wanted to directly grab one or two values, but make sure the *rest* are still captured? 
We can use 2 other ES6 features - **the rest parameter** and **spread syntax**. Using spread syntax (`...`) before a variable name creates the rest parameter. Sometimes you'll hear this referred to as the "rest pattern". 

Using the rest pattern is like selectively placing a couple of values in special boxes that can contain only one thing, and throwing the rest into a larger, catch-all box in case we need them later on. 

```jsx
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 
const [ first, second, ...rest ] = numbers; 
console.log(rest);
//---> [3, 4, 5, 6, 7, 8, 9, 10]

const colors = ["red", "blue", "green", "yellow", "purple", "orangered", "goldenrod"];
const [ primary, secondary, accent, ...others ] = colors; 
console.log(others); 
//---> ["green", "yellow", "purple", "orangered", "goldenrod"] 
```

Any name can be given to the rest parameter, but it *must* be proceeded by the spread syntax (...) and it *must* be the last variable in the destructuring array. If the rest parameter has a trailing comma it will throw an error. 

* **We can extract values from nested arrays** 

So far we've been working with single layer arrays, but destructuring works on nested arrays too. As always, position is important and the corresponding item must be an array. 

```jsx
const styles = [["desktop", [800, 100, "relative"]], ["mobile", [500, 80, "absolute"]]]; 
const [ [ className, [ height, width, position ] ] ] = styles;

console.log(className);
//---> "desktop"
console.log(height);
//---> 800
```

---

Now that we've seen the basics, let's look a couple of use cases for array destructuring. 

**Use Case 1: Working with returned arrays**

Functions commonly return an array. Using array destructuring can make working with returned arrays DRY-er and easier to read. 
In the function below, we return an array and assign their values using destructuring. You can see that we can skip values, assign the rest and more, just as before. 

```jsx
function dummy() {
    return [10, 50, 30, 50, 60];
}

const [ first, second, , ...rest ] = dummy();
console.log(first);
//---> 10
console.log(rest);
//---> [50, 60] 
```

**Use Case 2: Swapping values** 

One very handy use case of destructuring is swapping the contents of two variables. Before ES6 this required creating a temporary variable. 

```jsx
let first = "one"
let second = "two"
// temporary variable
let originalFirst = first;
// swap the values
first = second; 
second = originalFirst;
console.log(first, second)
//---> "two" "one"
```

First a new variable, `originalFirst`, is created to capture the value of `first`, ("one"). Then `first` is directly reassigned to point to the value of `second`, ("two"). Finally `second` will be pointed to the value we captured in the temporary variable. If we didn't do this the original value of `first` would be lost upon reassignment. 

Using destructuring removes the need for a temporary local variable, and several lines of code altogether. In the destructuring array we'll declare the variables, and then swap them in the assignment, effectively trading values. 

```jsx
let first = "one"
let second = "two" 
[ first, second ] = [second, first]; 
console.log(first, second); 
//---> "two" "one"
```

**Use Case 3: Regex patterns!** 

Regular expressions, *regex* for short, provide us a way to search a string against a pattern. Using the `exec` function returns an array where the first element is the entire match, and the following elements are the smaller captured matches. 

To illustrate what I mean, we'll look at a common regex pattern - the date matcher. 

```jsx
// this is a regex pattern - and a handy one to know!
const datePattern = /^([a-z]+)\s+(\d+)\s*,\s+(\d{4})$/i; 

let [ fullDate, month, day, year ] = datePattern.exec("December 20, 2020") || []; 

console.log(fullDate, month, day, year); 
//---> "December 20, 2020" "December" "20" "2020" 
``` 

The `exec` function takes in the pattern to be searched for, and the string to be searched. It returns an array, containing first the full match with all of its spaces and characters ("December 20, 2020"), and then the individual matches that were captured ("December" "20" "2020").

Note that after calling the `exec` function and passing in a string, we provided the logical `||` (or) operator and defaulted the return to be an empty array if no match could be found. 

Though this post isn't really about regular expressions, they're an incredibly valuable tool to have in your belt. They can be used to search for word, date, and other patterns in text - capable of being as broad or specific as needed. Read more about regular expressions [here](https://medium.com/factory-mind/regex-tutorial-a-simple-cheatsheet-by-examples-649dc1c3f285). 

---

#### Object Destructuring

Object destructuring is very similar to array destructuring, so we'll touch on it quickly, concentrating on the differences. We can extract properties much the same way we do with arrays, but instead of brackets, we use curly braces. 

```jsx
const dogs = {good: "Rover", gooder: "Sparkles", goodest: "Ace"}; 
const { good, gooder, goodest } = dogs;
console.log(good, gooder, goodest); 
//---> "Rover" "Sparkles" "Ace"
```

If arrays are obsessed with position, objects are obsessed with name. That being the case, the property name must be spelled correctly with casing in mind, or it will return undefined. 

```jsx
const dogs = {good: "Rover", gooder: "Sparkles", goodest: "Ace"}; 
const { good, Gooder, goodest } = dogs;
console.log(good, Gooder, goodest); 
//---> "Rover" undefined "Ace"
```

If we're not interested in a value we don't need to intentionally skip it. Instead, we can simply omit the property name. Position doesn't matter, we need only to be aware of the property names we're interested in, and their location relative to depth. 

```jsx
const dogs = {good: "Rover", gooder: "Sparkles", goodest: "Ace"}; 
const { good, goodest } = dogs;
console.log(good, goodest); 
//---> "Rover" "Ace"
```

* **We can assign values after declaration - with one gotcha**

If we assign a value to a variable without a declaration, we must wrap the assignment statement in parentheses. 

```jsx
let first, second; 
({ first, second } = {first: 1, second: 2}); // assignment statement
console.log(first, second);
//---> 1 2
```

If these parentheses are left out the statement will be read as a block, instead of an object literal destructuring assignment. They are not required when the declaration is present.

* **We can provide default values and assign the Rest**

We can capture the rest, and assign a default value, the same way we do in array destructuring - the only difference is the curly brackets. 

```jsx
const topDogs = {
  first: "Rover", 
  second: "Marshmallow", 
  third: "Kurt", 
  honorableMentions: {
    costume: "Sparkles", 
    personality: "Buccaneer"
  }
}; 

const { first, third, fourth = "Cocoa", ...rest } = topDogs;

console.log(first, third, fourth); 
//---> "Rover" "Kurt" "Cocoa"
console.log(rest);
//---> Object {honorableMentions: Object {costume: "Sparkles", personality: "Buccaneer"}, second: "Kurt"}
```

* **We can provide an alias** 

If we want our identifier to have a different name than the property, we can provide an alias. Call the property name as usual, followed by a colon and the desired name. 

```jsx
const topDogs = {
  first: "Rover", 
  second: "Marshmallow", 
  third: "Kurt", 
}; 

const { first: gold, second: silver, third: bronze } = topDogs;
console.log(gold, silver, bronze);
//---> "Rover" "Marshmallow" "Kurt"
```

* **We can extract values from nested objects**

The properties on the objects we've seen so far have contained primitive data types, but they can also contain complex structures, like another object. We can use destructuring to access values in these nested structures. 

```jsx
const topDogs = {
  first: "Rover", 
  second: "Marshmellow", 
  third: "Kurt", 
  honorableMentions: {
    costume: "Sparkles", 
    personality: "Buccaneer"
  }
}; 

const { honorableMentions: { costume: bestDressed } } = topDogs;
console.log(bestDressed); 
//---> "Sparkles"
```

I like to think of these statements as a map with legend. `honorableMentions` is not an identifier, or a variable. If we try to log it and peak at its guts, we won't find anything. 
It just lets the compiler know to look for a nested object with name `honorableMentions` on the first level of the sourced object, reach into it and grab the value of the property with name `costume` and copy the value found there into our identifier `bestDressed`. 

We can extract values an unlimited amount of levels down. We just need to keep track of how many levels deep we are (with the presence of brackets) and how many stops there are on the way (with property names). 

Without destructuring we could accomplish the same result with dot or bracket notation. 

```jsx
const topDogs = {
  first: "Rover", 
  second: "Marshmellow", 
  third: "Kurt", 
  honorableMentions: {
    costume: "Sparkles", 
    personality: "Buccaneer"
  }
}; 

console.log(topDogs.honorableMentions.costume); 
//---> "Sparkles"
```

---

**Use Case: Destructuring props**

Working with the props system in React often involves working with large, complex objects. Here destructuring can really shine - making components not only easier to read, but easier to write. 

In this contrived example, we're passing a card object to a card viewing component through props. 

```react
import React from "react";
import "./styles.css";
import CardViewer from './CardViewer'; 

const cardData = {
  front: "What does padding refer to in CSS?", 
  back: "Padding refers to the space between the border of the element and the content of the element", 
  user_id: 1, 
  public: true, 
  active: true, 
  notes: ["if border-box sizing is used padding will not effect the size of an element", "padding 'pads the content'"]
}; 

export default function App() {
  const card = cardData; 

  
  return (
    <div className="App">
      <CardViewer card={card} />
    </div>
  );
}
```

Without destructuring we have to repeatedly use the `props` prefix, and any further prefix needed, to get to the correct data in the `CardViewer` component.  

```react
import React, { useState } from "react";


const CardViewer = (props) => {
   const [ flipped, setFlipped ] = useState(false); 

   const flipCard = (e) => {
     e.preventDefault(); 
     setFlipped(!flipped);
   }


  return(
    <div onClick={flipCard}>
      <h3> {flipped ?
             `${props.card.back}` : 
             `${props.card.front}`}
      </h3>

      <div>
        <p>Notes:</p>
        <ul>{props.card.notes.map((note)=>{
          return <li>{note}</li>
        })} </ul>
      </div>

    </div>
  )
}

export default CardViewer; 
```

Using destructuring we can easily grab the values we need in the component parameters, then in the return need only include the `card` prefix. 

```react
import React, { useState } from "react";


const CardViewer = ({ card }) => {
   const [ flipped, setFlipped ] = useState(false); 

   const flipCard = (e) => {
     e.preventDefault(); 
     setFlipped(!flipped);
   }


  return(
    <div onClick={flipCard}>
      <h3> {flipped ?
             `${card.back}` : 
             `${card.front}`}
      </h3>

      <div>
        <p>Notes:</p>
        <ul>{card.notes.map((note)=>{
          return <li>{note}</li>
        })} </ul>
      </div>

    </div>
  )
}

export default CardViewer; 
```

We can take it even further with nested destructuring - grabbing only the things we're truly interested in. The resulting return reads almost like a sentence.  

```react 
import React, { useState } from "react";


const CardViewer = ({ card: { front, back, notes: [ ...notes ] } }) => {
   const [ flipped, setFlipped ] = useState(false); 

   const flipCard = (e) => {
     e.preventDefault(); 
     setFlipped(!flipped);
   }


  return(
    <div onClick={flipCard}>
      <h3> {flipped ?
             `${back}` : 
             `${front}`}
      </h3>

      <div>
        <p>Notes:</p>
        <ul>{notes.map((note)=>{
          return <li>{note}</li>
        })} </ul>
      </div>

    </div>
  )
}

export default CardViewer; 
```
---

Destructuring is another invaluable ES6 feature, allowing us to extract properties and values the same way we can construct them with object literals. Destructuring saves time, reduces confusion and can result in elegant, readable code. 

The next time you're working with complex data structures, keep this feature in your back pocket and you might just save yourself some time and headaches. 

---

***Resources***

[Eloquent JavaScript](https://eloquentjavascript.net/) - Marijn Haverbeke

[The Babel Replit](https://babeljs.io/repl#?browsers=&build=&builtIns=false&spec=false&loose=false&code_lz=Q&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=&prettier=false&targets=&version=7.12.11&externalPlugins=) - Always a good place to toss some code in and learn what it does under the hood

[Array Destructuring in ES6](https://www.freecodecamp.org/news/array-destructuring-in-es6-30e398f21d10/) - FreeCodeCamp

[Destructuring Assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) - MDN Web Docs 

[ES6 Destructuring: The Complete Guide](https://codeburst.io/es6-destructuring-the-complete-guide-7f842d08b98f) - Glad China, CodeBurst

[Destructuring Assignment](https://javascript.info/destructuring-assignment) - Javascipt.info

[Destructuring](https://exploringjs.com/es6/ch_destructuring.html#sec_overview-destructuring) - exloringjs.com 

[Destructuring Regular Expression Matching](https://mariusschulz.com/blog/destructuring-regular-expression-matches-in-ecmascript-2015) - Marius Schulz

[JavaScript Object Destructuring](https://dmitripavlutin.com/javascript-object-destructuring/) - Dmitri Pavlutin

[Destructuring & Function Arguments](https://davidwalsh.name/destructuring-function-arguments) - David Walsh

[Destructuring Props in React](https://medium.com/@lcriswell/destructuring-props-in-react-b1c295005ce0) - Lindsay Criswell, Medium

🦄 Thanks for reading!