4 Ways to Level-Up Your JS Destructuring and Spread Syntax
Tags: javascript, react, programming
Published: 2022-01-11 04:29:28

If you're a fan of Javascript and reading dev articles, you might share my addiction of clicking on every article with a title **_'X number of cool JS tricks'_.**
 I've probably read 40-50 of them. Most of the ones that I found really handy were to do with destructuring and spread syntax. I thought I'd consolidate the best tips here.

##1. Destructuring an array with index numbers

Destructuring is a great way to pull exactly what you need from a data set. However, with arrays it can be frustrating if you need a property a few indexes down the line and don't care about the first few.

I'm sure you've seen syntax like this before where properties are omitted using commas:

```javascript
const fruits = ['🍎', '🥭', '🍉', '🍋']
const [,,, lemon] = fruits
console.log(lemon) // 🍋
```
To me this looks messy. A developer has to look at the number of commas to understand which properties were taken from the array and if you need grab a few values not next to each other it can become very unwieldy.

Thankfully, in JS, arrays are really just objects under the hood. The index is the key and the array property is the value. 

```javascript 
const fruits = ['🍎', '🥭', '🍉', '🍋']
// {0: '🍎', 1: '🥭', 2: '🍉', 3: '🍋'}
```

What this means is we can use object destructuring on our array. We can use the index of the properties we want to access to pull them from the array.

```javascript
const fruits = ['🍎', '🥭', '🍉', '🍋']
const {3: lemon} = fruits
console.log(lemon) // 🍋
```
Now a developer can see exactly which property you took by checking the index. Also if you need multiple values that are not neighbours there's no need to awkwardly count the amount of commas that should be between them.

##2. Filtering with spread and destructure

Removing properties from an object can be pretty straightforward. Simply use the `delete` keyword and you're on your way.

```javascript
const food = {watermelon: '🍉', apple: '🍎', mango: '🥭', fries: '🍟'}
delete food.fries
console.log(food) // {watermelon: '🍉', apple: '🍎', mango: '🥭'}
```
This is fine if you're happy with your object being mutated.
However, objects can be passed around into different functions and accessed in several places, so suddenly removing a property could cause issues. 
  For this reason it's usually a safer idea to leave your initial object intact and create a new one for your filtering.

We can achieve this by using destructuring to separate the unwanted property or properties from the rest of the object.

```javascript
const food = { watermelon: '🍉', apple: '🍎', mango: '🥭', fries: '🍟' }
const { fries, ...fruits } = food
console.log(fruits) // { watermelon: '🍉', apple: '🍎', mango: '🥭' }
```
Note that compared with mutating the original object, we now have a new object with a suitable name to indicate more clearly what the object now contains.

_One caveat with this method is linters may underline the property you're removing (in this case `fries`) as the variable won't be referenced anywhere._

## 3. Optional Object Building

Sometimes we want to build an object conditionally. I usually find myself in such a predicament when I need to send data to an api. An api request could need different parameters depending on the state the application is in.

One approach might be to use some `if` statements.

```javascript
const params = { }
if (id) params.id = id
if (pageNumber) params.pageNumber = pageNumber
await axios('https://endpoint.com/data', {params})
```
This works fine, but can get bloated quickly. I also personally prefer to instantiate the object with the properties it needs from the get-go.

We can achieve this by taking advantage of the fact that falsey values will be ignored when spread into an object.

```javascript
const params = { id: 131, ...false }
console.log(params) // { id: 131 }
```

So to conditionally add properties we need to check the property isn't falsely and if so add it to our object.

```javascript
const params = { id: 131, ...(pageNumber && {pageNumber}) }

// Page number falsey value
console.log(params) // { id: 131 }

// Page number truthy value
console.log(params) // { id: 131, pageNumber: 2 }
```
So breaking this down, we start with the spread syntax for our conditional property. We then add parentheses to allow us to group our short circuit logic. 

If `pageNumber` is a falsey value the logical `&&` will exit with a falsey value which won't add anything to our object when spread.

If `pageNumber` is truthy however, the short-circuit logic will return the property we want to add and spread it into our object.

So refactoring the api example.

```javascript 
const params = {
  ...(id && { id }),
  ...(pageNumber && { pageNumber })
}
await axios('https://endpoint.com/data', { params })
```
To me this is much nicer. We've avoided instantiating an empty object at the beginning like with the `if` statement example and all possible params that might be sent to the api can be seen directly on the object rather than combing through the `if` statements for possibilities.


## 4. Destructuring length from array

Relating to the first tip, you can take it a step further by destructuring the length of an array. 
  You might ask how this is useful, but say you needed the last element of a huge dynamic array. You couldn't destructure this last element with either the comma method or the index method, as the last element would be a different index as data was added. So you could use the length property to grab the last element when destructuring.

```javascript
const bigDynamicArray = ['✌','😂','😝','😁','😱','👉','🙌','🍻','🔥','🌈','☀','🎈','🌹','💄','🎀','⚽','🎾','🏁','😡','👿','🐻','🐶','🐬','🐟','🍀','👀','🚗','🍎','💝','💙','👌','❤','😍','😉','😓','😳','💪','💩','🍸','🔑','💖','🌟','🎉','🌺','🎶','👠']

const { length, [length-1]: lastItem } = bigDynamicArray
console.log(lastItem) // 👠
```
So first we pull out the length. We then use a [computed property name](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#computed_property_names) to access correct index and finally give a name to our last item.

I will add this tip is approaching the territory of too clever for its own good. You don't want to burden other developers with understanding some abstract functionality for what could have been a rudimentary, yet simple to understand piece of code.



**Thanks for reading let me know if there's anything I missed or if you have some better tips and happy JS'ing!**