5 JavaScript Features That You Might Not Know About

Learn 5 extremely useful JavaScript features to use in your next line of code

Mario Eldin
6 min readMar 2, 2021

JavaScript is a hefty programming language with a vast amount of features that makes it possible to implement complex features in applications to make the world a better place — well, that’s how I see it.

Moving on to the goods, let’s not let this linger any longer. We will be discussing these 5 JavaScript features:

1. Optional Chaining

2. Nullish Coalescing

3. Styling Console Log

4. Defer/Async Loading

5. Object Shorthand

Optional Chaining

What is optional chaining? It’s an operator that was introduced as a new feature in ES2020 and it permits you to access the value of a property that’s located deep inside a chain of objects without the extra work of checking if each reference in the chain is null or undefined .

Let’s say one of the references in this chain of objects is null or undefined, the optional chaining operator will short circuit and return undefined.

It looks like this: ?.

Cool, right? But how does it look in action? We will get there soon, let’s break this down first.

In this example we are going to use a special function.

class Sandwich {
constructor(bread, toppings){
this.bread = bread
this.toppings = toppings
};
printOrder(){
console.log(this);
}:
};
let printVeggieToppings = (sandwich) => {
console.log(sandwich.toppings.veggie);
};
const yourSandwich = new Sandwich(
'Multigrain',
{
meat: 'Tofu',
cheese: 'Vegan Swiss',
veggie: 'Cucumbers'
},
);
yourSandwich.printOrder();
printVeggieToppings(marioSandwich);

We declared a class called Sandwich, created a yummy object , and we’ll pass delicious arguments to our constructor parameters — because food is always the answer.

Inside of our class we also declared a static method printOrder that will log our object in the console. Moving on, we declared a function printVeggieToppings that will log the veggie topping of our delicious sandwich.

Right after, we’ll declare yourSandwich variable and set its value to a new instance of our Sandwich object, and finally invoke printOrder and printVeggieToppings.

What should we see in our console?

Sandwich {
bread: 'Multigrain',
toppings: {
meat: 'Tofu',
cheese: 'Vegan Swiss',
veggie:'Cucumbers'
}
}
Cucumbers

The invocation of printOrder logs our Sandwich object and printVeggieToppings logs the value of the property veggie.

Perfect.

What would we see in the console if we pass undefined as an argument to our toppings parameter?

TypeError: Cannot read property 'veggie' of undefined

Why? Because JavaScript is trying to access toppings.veggie while toppings is undefined, so it throws an error. This is an error in JavaScript that you can run into frequently and here are two ways you would usually go about it pre-optional chaining operator.

let printVeggieToppings = (sandwich) => {
console.log(
sandwich && sandwich.toppings && sandwich.toppings.veggie
);
};

OR

let printVeggieToppings = (sandwich) => {
if(sandwich && sandwich.toppings){
console.log(sandwich.toppings.veggie)
}
};

Both options will result in undefined and will not throw an error. In the first solution it will short circuit once it reaches sandwich.toppings and in the second solution it will never enter the scope block because the condition is not met.

Here comes the optional chaining operator ?.. Instead of writing all that code, we can keep our original code block and simply add a ? to it like this:

let printVeggieToppings = (sandwich) => {
console.log(sandwich?.toppings?.veggie);
};

Clean right? What’s happening here though?

Let’s recap.

JavaScript is checking if sandwich is a null or undefined value, if not, it will keep going down the chain of objects and keep checking. However, if there’s a null or undefined value anywhere in that chain of objects it will short circuit and log undefined in our console and not throw an error.

Otherwise, it will log the property’s value, in our case that’s Cucumbers. Also, it would be good to mention that this would work with functions as well.

Here is an example using our printOrder function.

class Sandwich {
constructor(bread, toppings){
this.bread = bread
this.toppings = toppings
};
printOrder(){
console.log(this);
}:
};
const yourSandwich = new Sandwich(
'Multigrain',
{
meat: 'Tofu',
cheese: 'Vegan Swiss',
veggie: 'Cucumbers'
},
);
yourSandwich.printOrder?.();

At the very bottom you’ll see yourSandwich.printOrder?.() — that looks weird, I know.

JavaScript in this example is not only checking if printOrder exists, it’s also checking if it’s a function! If it does exist and it’s actually a function, then it will successfully execute and log our Sandwich object to the console. If it does not exist or it’s not a function, we find a nice undefined waiting for us in the console.

Nullish Coalescing

If you thought optional chaining operator was cool, you’re going to love nullish coalescing operator. What is it?

MDN Web Docs said it best — “a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, and otherwise returns its left-hand side operand”.

It looks like this: ??

Let’s jump right into an example.

let favNumber = (num) => {
num = num || 'No number for you';
console.log(`Your favorite number is: ${num}`);
}
favNumber(9);

What would we see in our console when favNumber is invoked?

Your favorite number is: 9

Now, what if someone’s favorite number happened to be 0 and we invoke favNumber(0) like this?

Your favorite number is: No number for you

The OR operator returns the right-hand side operand if the left-hand side operand is any falsy value, not just null or undefined. Let’s swap the OR operator with the nullish coalescing operator.

let favNumber = (num) => {
num = num ?? 'No number for you';
console.log(`Your favorite number is: ${num}`);
}
favNumber(0);

The nullish coalescing operator returns the left side operand if the right-hand side operand is null or undefined value and that’s why we’d see this in our console.

Your favorite number is: 0

Styling Console Log

The next time you’re using the console — splash some styling! In the example below we used two CSS styles, font-size and color, each were passed as an argument to the console.log(). For each CSS style that gets passed as an argument you’ll need to add %c before the text you’d like to style.

Defer/Async Loading

Let’s say we have a test.html file and we link an external JavaScript file to it called index.js using a script tag. The index.js file looks a little something like this:

//index.jsconst title = document.querySelector("h1");title.style.color = "blue";

Usually you’ll find the link to an external JavaScript file nested under the body tag of the HTML file, like this:

//test.html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>This needs to load NOW!</h1>
<script src="index.js"></script>
</body>
</html>

The thing with having the script tag right above the closing body tag is that the download of your script tag doesn’t start until the browser gets to it, and since it’s the last thing to download in test.html, the browser will read it last and that could slow down your download speed.

Instead, you can place your script tag like this:

//test.html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="index.js" defer></script></head>
<body>
<h1>This needs to load NOW!</h1>
</body>
</html>

Take a closer look, not only did we change the script tag’s placement, we added the defer attribute right after the src attribute — and that makes all the difference. By using the defer attribute it tells the browser not to wait for the script and to continue to process the HTML, and build the DOM. Under the hood the script loads “in the background”, and then runs when the DOM is fully built.

It’s good to keep in mind these two key characteristics of the defer attribute:

  • Scripts with defer always execute when the DOM is ready (but before DOMContentLoaded event).
  • Scripts with defer never block the page.

Object Shorthand

Object shorthand was introduced with ES6 and it’s quite clean looking when implemented. Lets say we have two variables:

const choiceOfCar = 'Jeep';
const makeOfCar = 'Wrangler';

We want to use these variables in an object called car as key-value pairs. If we were to use the ES5 syntax, our object would like this:

const choiceOfCar = 'Jeep';
const makeOfCar = 'Wrangler';
const car = {
choiceOfCar: choiceOfCar,
makeOfCar: makeOfCar,
};

However, with ES6 syntax our car object would look like this:

const choiceOfCar = 'Jeep';
const makeOfCar = 'Wrangler';
const car = {
choiceOfCar,
makeOfCar,
};
console.log(car);

The object shorthand converts the variable name to a key and will set the key’s value as the variable’s value. If we would log the car object to our console, this is what we’d see:

{ choiceOfCar: 'Jeep', makeOfCar: 'Wrangler' }

Thank you for reading! Hope you found this useful, share if you did.

Connect with me on LinkedIn or Instagram: @marioeldin

Have a great day/night!

— Mario Eldin

--

--

Mario Eldin

I have deep passion for debugging and building full-stack applications, and enjoy doing so from different corners of the world.