Selecting multiple DOM elements with destructuring and map
Tags: javascript, dom, tip
Published: 2019-06-23 19:43:18

---
title: Selecting multiple DOM elements with destructuring and map
published: true
description: A simpler way of retrieving and storing DOM elements with id, using destructuring, map and arrow functions
tags: javascript, dom, tip
---

If you are working with vainilla JS and manipulating DOM elements, I'm sure earlier than later you found yourself with code like this:

```javascript
const sendButton = document.getElementById('send-btn');
const discountPopUp = document.getElementById('discount-popup');
const messageInput = document.getElementById('message');
const calculateButton = document.getElementBy('calculate-btn');
// dozens of elements more
``` 

Please don't take this example too serious. I'm not saying this is good code or even these are good named constants and ids. I just wanted to show that this code can be simplified using some awesome ES6 features: `map` and destructuring. We could do the following:

```javascript
const [sendButton, discountPopUp, messaInput, calculateButton] = ['send-btn', 'discount-popup', 'message', 'calculate-btn'].map(id => document.getElementById(id));
``` 

Why does this work? Let's go step by step.

First, `map` is an `Array` method that takes a function as callback. Then, for *each* element of the array, executes the callback, pasing the element as a parameter of the callback. The return of that callback is added to a new array. So, as the name says, `map` **maps** the elements of an array to a new array, *passing* each element through a function.

For example,

```javascript
const numbers = [1, 2, 3, 4];
const doubles = numbers.map(number => number * 2);
console.log(doubles); // [2, 4, 6, 8];
```

`map` here is *mapping* each number to its double, and storing it in the new array `doubles`.

The callback is written as an *arrow function*. The arrow function doesn't need to declare the reserver word `return` if the only thing that does is returning some value. If that is not too clear, we could rewrite the arrow function like:

```javascript
const doubles = numbers.map((number) => { return number * 2});
```

but as you can see, the first one is more concise. Even more, we don't need the constant `numbers`, we can use map directly on the array:

```javascript
const doubles = [1, 2, 3, 4].map(number => number * 2);
```

Awesome, rigth?, So, back to our example, we had:


```javascript
const elements = ['send-btn', 'discount-popup', 'message', 'calculate-btn'].map(id => document.getElementById(id));
``` 

Here we have an array with ids, and *map* is mapping each of those strings to a HTML element, since the callback takes an id and returns a HTML element with that id. Those elements are stored in a new array, `elements`. 

But that is not very helpful. If now we want to use the element with id *'message'*, we need to retrieve it like:

```javascript
elements[2]
```

This doesn't say much. Imagine using it 100 lines later. What the heck `elements[2]` is?

Of course we can avoid this storing it in a variable, but that take us back to where we begin.

```javascript
const elements = ['send-btn', 'discount-popup', 'message', 'calculate-btn'].map(id => document.getElementById(id));

const sendButton = elements[0]
const discountPopUp = elements[1];
const messageInput = elements[2];
const calculateButton = elements[3];
// dozens of elements more
``` 

Which is not very practical. Instead of that, we can *destructure* the array which `map` returns. You can image destructuring an array as taking each of its elements and storing it in a variable.

For example:

```javascript
let [a, b, c] = [0, 1, 2];
console.log(a); // 0
console.log(b); // 1
console.log(c); // 2
```

Each element of the array on the right is stored in its respective variable, in order. The first element of the array in the right is stores in the first variable of the left, and so on.

So, knowing this, we can finally end where we started.

```javascript
const [sendButton, discountPopUp, messaInput, calculateButton] = ['send-btn', 'discount-popup', 'message', 'calculate-btn'].map(id => document.getElementById(id));
```