The Chronicles of a Rookie Developer: JavaScript Insights
Tags: javascript, webdev, codenewbie, todayilearned
Published: 2021-12-22 15:52:42

###Pretext

After building out my first-ever vanilla JS + Rails API application, I thought back on the experience and skimmed through my code to gather ideas on what I could blog about. The truth is, there were many bits and pieces that I learned but I didn't feel like I knew nearly enough about each topic to solely dedicate an entire blog post. (Not to mention I also suffer from chronic indecisiveness.) So I apologize in advance but I decided to just list them all. **_Here are 4 things I learned, attempted, or simply found interesting about JavaScript_**.

###One. To function, or not to function, that is the question.

In JavaScript, and particularly vanilla JS, you're most likely going to declare and use these so-called *node getters* where you grab elements from the DOM using a method such as (but not limited to) `querySelector()` in combination with one or more valid CSS selector strings (like classes or ids). And when you find yourself querying for the same node multiple times at difference places in your code, it makes sense to assign it to a variable and extract it to a more global scope, right?
Now, I know that when we first start learning to code, this notion of declaring variables in the global scope is a big no-no and it gets reiterated over and over as we're often told that it can lead to some unexpected behaviors down the road and should therefore -- when possible -- be avoided. But for now, let's just assume that our application is extremely small and there is very little to no reason to sound the alarm. The question, then, is whether to wrap these node getters into a function or to just have it point directly to the node. 
For instance, you might've seen someone do something like
`const mainContainer = () => document.querySelector('div.main')`
versus something like
`const header = document.querySelector('#header')`.
So which way is better? The answer, I've found, is that it really **_depends_**.

There's this subtle yet sweet balance between what you are trying to accomplish with the node and whether the node exists or doesn't exist inside a particular execution context.

The benefit of using a function to grab your node is that you can always ensure you are selecting the most recent version of it since you are calling the query at the exact moment you need it. This is particularly useful when perhaps you need to grab a node that doesn't exist immediately on initial load but is something that gets created later in your code (as a result of a callback, for instance). I'd say 9 times out of 10, this is probably going to be your **_preferred_** method.

However, the opposite can also be true. I ran into an occasion where it made more sense to point directly to the node, and it was something as simple as wanting to `remove()` a header from the page and later re-attach that **_same exact node_** back on the DOM. In this case, if we were to use a function, we would not be able to find the node since it would no longer exist on the `document` and we would instead have to re-create the element. But luckily for us, JavaScript has garbage collection, meaning it will store it in memory and give us access to it even after it's been removed from the DOM as long as we point it to a variable. It then goes without saying that this would probably merit some thought in all future applications in order to ensure that we are always effectively preventing unnecessary memory leaks.

###Two. Two is always better than one, or is it...?

The thing I'm talking about here is none other than the **DRY principle** of programming and my humble attempt to combine two functions into one. I've learned by now that refactoring code is just a regular part of any programmer's life and should become second nature sooner rather than later. So as I examined for areas to abstract, I noticed that my fetch functions were carrying a lot of code and particularly noticed similarities between my `POST` and `PATCH` requests. The data being sent was identical, the fetch `url` was identical except for the presence of an `id` (thanks to RESTful routing), and the `init` object was identical except for the `HTTP method`. It seemed to check everything off the list for a potential refactor.

First I should start by mentioning that I've built my application in an object-oriented pattern using ES6 class syntax and therefore have a separate `Adapter` class that handles all fetches.
Sticking to conventions of **CRUD**, I've got a static `createRecord()` and `updateRecord()` method within the `Adapter` class, each responsible for sending the appropriate fetch request. I also have one other static property, `baseURL`, and two other static methods defined, `setDataObj()` and `setInitObj()`. `baseURL` (as the name suggests) simply stores the base URL to which we will be sending our fetch requests while `setDataObj()` is responsible for constructing the object that we will be sending off to the backend and contains all of the input values from a form. It looks something like this:
```javascript
static setDataObj = () => {
    const name = form().querySelector('#name').value;
    const description = form().querySelector('#description').value;

    const data = {
        name,
        description
    };

    return data;
};
```
Notice that it returns the data object, as this will be useful to us in the next step.
Then in my `setInitObj()` method, I take in a string argument for the type of request -- `POST`, `PATCH`, or `PUT` -- then use it to build out an options object.
```javascript
static setInitObj = (method) => {
    const options = {
        method: method,
        headers: {
            "Content-Type": "application/json",
            Accept: "application/json"
        },
        body: JSON.stringify(Adapter.setDataObj())
    };

    return options;
};
```
Notice that I am now able to simply pass in `Adapter.setDataObj()` to `JSON.stringify()` since we made it return the object we need.
`setInitObj()` then returns yet another object, which we can use in our fetch method both in `createRecord()` or `updateRecord()`, passing in the proper HTTP verb with it:
```javascript
static createRecord = () => {
    fetch(Adapter.baseURL, Adapter.setInitObj('POST'))
        ...
};
```
```javascript
static updateRecord = (id) => {
    fetch(Adapter.baseURL + id, Adapter.setInitObj('PATCH'))
        ...
};
```
Now in my event handlers, or anywhere in my code where I need to send off the form data, I can simply call `Adapter.createRecord()` or `Adapter.updateRecord(id)`.

###Three. Being conscious of how often we fetch.

Personally, this was more of a food for thought than anything else because I'm guilty of not following my own advice but I **_did realize_** the importance of code design, particularly how I wish to maintain the data on the front-end after a fetch. Because this was my first experience with JavaScript, and especially because I was using functional vanilla JS instead of object-oriented JS or some other library, I chose the easy way out and saved myself a few headaches by re-fetching at times. Not *ALL* the time, but in certain situations. At least now I definitely see how I **_could_** have done things and it will come in handy as I think about incorporating more features on my app like sorting and filtering.
*(Note: This was something I wanted to share at the time of originally writing this post but have since rebuilt my entire project into object-oriented JavaScript and am now dealing with my front-end data in a much different manner.)*

###Four. Default behavior of an HTML5 button is submit.

Last but not least, I was enlightened during one of my debugging sessions that, apparently, the default behavior of a button is `submit` unless specified otherwise. Maybe this was just me but for some reason I always thought `<button>` tags did not have a default behavior as opposed to `<input type="submit">`. This would matter less if the button isn't enclosed in a `<form>` but if you're ever trying to use buttons inside a form for something *other than submitting the form*, you have to either specify the button's type attribute as `type="button"` or, alternatively, use `preventDefault()` in its event handler. Again, this might've been obvious to most but I hope someone else out there might find it useful to know!

If you've made it this far, thank you for reading. Stay tuned for the next edition of *The Chronicles of a Rookie Developer* as I continue my journey! Until next time!