Array and Object Manipulation + DOM differences
Tags: javascript, tutorial, programming
Published: 2022-05-19 01:39:53

For too long _(about a few weeks)_, I have second guessed myself every time I've started writing a For... loop. Here, I will show you how to know which one you should use for the task at hand, what can happen when you choose the wrong one, and how this extends to DOM elements. 

## For... of
When handling arrays of data, using a For...of loop is a great option.
![array logging](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9gqkct6enhil1anyo6zb.png)
Every time the loop is entered here, a new entry from the array is loaded into the value of i. The first console.log here will show i as being equal to the value of array[0], or 'apple'. The second as 'banana' and so on. Note that i is _not_ equal to the _index_ value of the item.

## For... in
Now for objects, a For...in loop is what you want to use. I like to imagine that I'm looking **in**side of the object to see all the keys and values. 
![object logging](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs18qwjn7dn9rxh4rvuo.png)
For this type of loop, every time i is reassigned, it gets a new _key_. Now, let's change our objectLogger function to see if we can view the values instead.
![object value logging](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvmvwqav80r1q7pclixq.png)
By choosing to log object[i] instead of i, we can see every _value_ in our object. So by using this type of loop, we can gain complete insight into every key:value pair in our object. An important thing to keep in mind when accessing objects like this is to NOT use dot notation and instead use the _computed member access operator_, aka **brackets**, for getting object properties. In this function, attempting to console.log object **. i** results in an undefined error as JavaScript tries to look through the object for a key literally called i.
 

## What happens if we forget? 
In the case of trying to treat an object as if it were an array, disastrous consequences will immediately occur and your IDE will make that clear as soon as you try to run the code.
```JavaScript
arrayLogger(animalObject)
// will return the following:
index.js:6 Uncaught TypeError: array is not iterable
    at arrayLogger (index.js:6:25)
    at HTMLDocument.<anonymous> (index.js:24:5)
```
However, in the case of treating an array as an object, something interesting happens.
```JavaScript
objectLogger(fruitArray)
//=> apple, banana, cantaloupe
```
You are actually able to treat an array as an object in JavaScript, because it **is**  a subtype of object.

Check it out:
```JavaScript
console.log(typeof fruitArray)
//=> object
console.log(typeof animalObject)
//=> object
```
_**Interesting.**_ This is also why it is also a terrible idea to use the _typeof_ operator to distinguish between an array and an object.

## DOM Elements and Notes on Handling Them
After some experimentation on a beautiful HTML page, I've been able to get a better handle on what exactly happens when putting together a collection of HTML/Node elements.
![html source code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tnrffkl34ksqy1mxlm9i.png)
> The relevant portion of my test HTML file.

![html + css output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yrcy2p1lawyqi2306sef.png)
> I'll spare you the eye-searing entirety of the output.

So let's see what happens when we gather the elements up in HTML collection form. 
```JavaScript
const divItems = document.getElementsByTagName('div')
console.log(divItems)
//=> HTMLCollection(7) [div, div, div, div, div, div, div]
for (const i of divItems) {
    console.log(i)
}
// will output :
 //   <div>Hey</div>
 //   <div>it's</div>
 //   <div>a</div>
 //   <div>whole</div>
 //   <div>bunch</div>
 //   <div>of</div>
 //   <div>divs!</div>
```
Okay, so this HTML collection is a type of array. But what if we handle it like an object?
```JavaScript
for (const i in divItems) {
    console.log(i)
}
// will output the following (numbers on one line for readability)
// 0, 1, 2, 3, 4, 5, 6
// length
// item
// namedItem
```
_Whoa_, secret properties. So this is why an HTML collection is a bit more substantial than a mere array. But let's get into the far superior querySelectorAll to see why I make that claim in the first place.
```JavaScript
const divList = document.querySelectorAll('section div')
console.log(divList)
//=> NodeList(7) [div, div, div, div, div, div, div]
for (const i of divItems) {
    console.log(i)
}
// will output :
 //   <div>Hey</div>
 //   <div>it's</div>
 //   <div>a</div>
 //   <div>whole</div>
 //   <div>bunch</div>
 //   <div>of</div>
 //   <div>divs!</div>
```
Alright so far, pretty much the same. Except it's called a _NodeList_. Whatever, right? But hang on, let's try to read it like an object.
```JavaScript
for (const i in divItems) {
    console.log(i)
}
// will output the following (numbers on one line for readability)
// 0, 1, 2, 3, 4, 5, 6
// entries
// keys
// values
// forEach
// length
// item
```
And there's why I like a NodeList more. It has the forEach method available for use because it is inherited from its Prototype (maybe I'll write about that later). If you expand the console.log for the HTML/Node collection as a whole and look at the last entry, you can spot the additional object 'keys' that are read by a For...in loop.
![console.log for a HTML collection](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbakjsf7rzy6ghjo22zd.png)
> Peering inside our HTML collection entry.

So if your goal is to iterate through bunch of HTML elements on a page, your best best is to querySelectorAll those bad boys and either use a For...of loop or a forEach method on them.

## TL;DR
Use a For... **of** loop on an array when you want to know the 1st, 2nd, or nth item **of** the array. Use a For... **in** loop on an object when you want to see the key:value pairs **in**side it. HTMLCollections and NodeLists are both a type of array, but only a NodeList has access to the forEach method.

_Thanks for reading!_