DEV Community ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป

Cover image for 12 Things EVERY JavaScript Developer Should Know ๐Ÿ•›
Dom (dcode)
Dom (dcode)

Posted on

12 Things EVERY JavaScript Developer Should Know ๐Ÿ•›

There's no better feeling than mastering a programming language. In today's post, we'll explore 12 things you should know if you're serious about JavaScript ๐Ÿ˜Ž

1. includes() Over indexOf()

Rather than checking for -1 to see if an array contains the given element, try using includes() instead, which returns a clean true or false:

const numbers = [3, 8, 2, 4];
const containsEight = numbers.includes(8);

// containsEight == true ๐Ÿ˜‰
Enter fullscreen mode Exit fullscreen mode

2. Using the defer Attribute

If you include your <script> tag at the end of your <body> tag, it's time to stop. Seriously. Instead, place your <script> tag in your <head> and use the defer attribute.

This will load the script asynchronously (speed โšก) and more importantly, only execute the script once the document has finished parsing:

<!DOCTYPE html>
<html>
    <head>
        <title>Subscribe to "dcode" on YouTube ๐Ÿคจ</title>
        <script src="js/main.js" defer></script>
    </head>
</html>
Enter fullscreen mode Exit fullscreen mode

3. const Over let

This is one of my favourites. Guess what? I hardly ever use let - because in most cases, you don't need to.

let should only be used when you know a variable will be reassigned (in other words, using the = sign). In all other cases, use const! ๐Ÿค“

const myButton = document.getElementById("myButton");
const numbers = [4, 0, 2, 3, 1];

// NOT reassignment
myButton.appendChild(someOtherDiv);

// NOT reassignment. It's a method call
numbers.push(5);
Enter fullscreen mode Exit fullscreen mode

4. Template Literals (Strings)

If you're trying to build up strings dynamically, there's almost never a reason to use ''s or "'s as of recent years. Instead, build strings in a clean manner using template literals (backtick):

const hour = "12";
const minute = "35";
const amPm = "pm";
const time = `It is ${minute} minute(s) past ${12}${amPm}`;

// time == It is 35 minute(s) past 12pm ๐Ÿ˜ง
Enter fullscreen mode Exit fullscreen mode

5. Logical OR (||) for Defaults

Most of you may already know this one, but it surprises me how often I don't see it being used. Let me keep it simple.

Replace this:

let username = localStorage.getItem("username");

// Can't find username, use a default
if (!username) {
    username = "Unknown";
}
Enter fullscreen mode Exit fullscreen mode

With this:

const username = localStorage.getItem("username") || "Unknown";
Enter fullscreen mode Exit fullscreen mode

Not only is it a single line of code, you also use const over let ๐Ÿ˜ฒ๐Ÿ‘†

6. Using classList Over className

What if I told you there was a smart way to interact with the classes on an HTML element? Well, you can with classList.

Let's have a look at a few examples:

const myButton = document.getElementById("myButton");

// Add a class
myButton.classList.add("color-primary");

// Remove a class
myButton.classList.remove("is-disabled");

// Toggle a class
myButton.classList.toggle("visible");

// Check if a class exists
myButton.classList.contains("border");

// Replace a class
myButton.classList.replace("color-warn", "color-success");

๐Ÿ˜
Enter fullscreen mode Exit fullscreen mode

7. Object Destructuring

JavaScript offers an intelligent way to take values from an object and reference them as variables or parameters - it's done through object destructuring:

const person = {
    name: "Dom",
    age: 28,
    occupation: "Software Developer",
    country: "Australia"
};

// Take the `name` and `country` from the `person` object
const {name, country} = person;

// Dom is from Australia
alert(`${name} is from `${country}`);
Enter fullscreen mode Exit fullscreen mode

And with function parameters:

function showMessage({name, country}) {
    alert(`${name} is from `${country}`);
}

showMessage(person);

๐Ÿฆ˜
Enter fullscreen mode Exit fullscreen mode

8. Array Destructuring

Similar to object destructuring, JavaScript offers the same thing for arrays, but it works through the index of an element:

    const color = [0, 149, 120];
    const [red, green, blue] = color;
Enter fullscreen mode Exit fullscreen mode

9. Array map()

This is probably one of the most under-used methods of JavaScript. It's called map() and is used to transform the elements of an array.

Let's take this numbers array and create a new array, which each number doubled:

const numbers = [4, 2, 8, 10];
const doubled = numbers.map(number => {
    return number * 2;
});
Enter fullscreen mode Exit fullscreen mode

This code is really simple - we pass a function into the .map() method, and it will run for each element in an array. The return value of this function is the new value for that element in the array.

10. Element closest()

PAY ATTENTION because this DOM method is my favourite. It comes handy very often, especially when building user interfaces or using a third-party library.

This method gives you context of a child element's parent element by searching up the DOM tree until it finds an ancestor matching the given selector.

In the example below, we are within a click event but we don't know where the event target (element that was clicked on) is in the document:

someUnknownButton.addEventListener("click", e => {
    const container = e.target.closest(".container");
});

/*
    The DOM tree might look like this:

    <div id="app">
        <div class="container">
            <div class="float-right">
                <button>Click</button>
            </div>
        </div>
        <div class="container"> <!-- โฌ…๏ธ end up here -->
            <div class="float-right">
                <button>Click</button> <!-- ๐Ÿ‘ˆ CLICKED -->
            </div>
        </div>
        <div class="container">
            <div class="float-right">
                <button>Click</button>
            </div>
        </div>
    </div>
*/
Enter fullscreen mode Exit fullscreen mode

11. Fetch API Over AJAX

It's time to stop using AJAX. Use fetch() for your client-side HTTP requests instead, it's a modern way to fetch data from your backend or API. As a bonus, you'll also get comfortable with promises.

Let's see how we can use fetch() over a traditional jQuery AJAX request:

// jQuery AJAX
$.get("/data/users.json", function(users) {
    console.log(users);
});

// Fetch API
fetch("/data/users.json").then(response => {
    return response.json();
}).then(users => {
    console.log(users);
});
Enter fullscreen mode Exit fullscreen mode

The Fetch API does look a little more complicated, but it's native to the browser, avoids callback hell and gives you easy access to the response object (to check status codes, content type etc.) โœˆ๏ธ

12. Async Await

Many developers are afraid to jump into the world of async/await, but trust me, give it a good shot - it really isn't too complicated.

To put it simply, async/await offers you an alternative way to deal with promises. You can avoid the verbose .then() syntax and make your code look more sequential.

Let's have a 2nd look at the previous Fetch API code example but using async/await over .then():

async function fetchAndLogUsers() {
    const response = await fetch("/data/users.json");
    const users = await response.json();

    console.log(users);
}
Enter fullscreen mode Exit fullscreen mode

You can see here, the await keyword breaks up each .then(), and if you wanted to, you can use try...catch to handle errors as opposed to catch() ๐Ÿ˜ง.

Video Guide

To see this post in video form, have a look on my YouTube channel, dcode

JavaScript DOM Crash Course

You can find a complete course on the JavaScript DOM which goes over some of the topics covered in this post at the link below ๐Ÿ‘‡
https://www.udemy.com/course/the-ultimate-javascript-dom-crash-course/?referralCode=DC343E5C8ED163F337E1
Course Thumbnail

Keep learning ๐Ÿ’ช

Top comments (5)

Collapse
lukeshiru profile image
Luke Shiru • Edited on

I have a few for you:

1. Use nullish coalescing (??) for defaults

Instead of using "Logical OR (||) for Defaults", you should be using ??, which will not go to the default with falsy values, only with nullish values:

const username = localStorage.getItem("username") ?? "Unknown"; // "Unknown" when "username" is missing
const falsy = 0 ?? "Unknown"; // 0 because it isn't nullish
Enter fullscreen mode Exit fullscreen mode

2. If an arrow function only has a return, put that after the arrow

If an arrow function like the one you used in your map example only has a return on it, you can skip that and just write it like this:

const numbers = [4, 2, 8, 10];
const doubled = numbers.map(number => number * 2);
Enter fullscreen mode Exit fullscreen mode

Same applies to your fetch example:

fetch("/data/users.json")
    .then(response => response.json())
    .then(console.log);
Enter fullscreen mode Exit fullscreen mode

3. Use async/await when it makes sense

Many developers default to async/await, which generally leads to code using those when they aren't needed because folks don't fully understand how promises work. Your async/await example is a good example of one of those cases where not using async/await makes the code shorter while keeping it readable:

// Yours
async function fetchAndLogUsers() {
    const response = await fetch("/data/users.json");
    const users = await response.json();

    console.log(users);
}

// Versus the shortest possible version using async/await
const fetchAndLogUsers = async () =>
    console.log(await (await fetch("/data/users.json")).json());

// Versus the shortest possible version not using async/await
const fetchAndLogUsers = () =>
    fetch("/data/users.json")
        .then(response => response.json())
        .then(console.log);
Enter fullscreen mode Exit fullscreen mode

You might argue that the async/await keeps being more readable, but then if we add a catch for errors, then theres a clearer "winner":

// Yours (with a catch)
async function fetchAndLogUsers() {
    try {
        const response = await fetch("/data/users.json");
        const users = await response.json();
        console.log(users);
    } catch (error) {
        console.error(error);
    }
}

// Versus the shortest possible version using async/await
const fetchAndLogUsers = async () => {
    try {
        console.log(await (await fetch("/data/users.json")).json());
    } catch (error) {
        console.error(error);
    }
};

// Versus the shortest possible version not using async/await
const fetchAndLogUsers = () =>
    fetch("/data/users.json")
        .then(response => response.json())
        .then(console.log)
        .catch(console.error);
Enter fullscreen mode Exit fullscreen mode

Cheers!

Collapse
jmau111 profile image
jmau111โญ

Nice synthesis, but you probably want to know the differences between indexof and includes rather than just using one method over a another because of the return value:

Collapse
jonrandy profile image
Jon Randy • Edited on

includes() Over indexOf()

Not really much difference - it's no shorter, and only a very marginal speed increase:

const numbers = [3, 8, 2, 4]
const containsEight = numbers.includes(8)

// or
const containsEight = ~numbers.indexOf(8)
Enter fullscreen mode Exit fullscreen mode

I guess readability could be considered an advantage with includes

Collapse
syeo66 profile image
Red Ochsenbein (he/him)

?? vs. || is certainly missing in this list. Especially since you are talking about defaults.

Collapse
vitalicus profile image
Vitalie Lisnic

N10 not undestanding

๐ŸŒš Friends don't let friends browse without dark mode.

Sorry, it's true.