7 Ways To Make Your JavaScript Better

0 Comments

It’s easy to learn how to code — especially in JavaScript. Once you’ve got things running, we tend not to look back and see how we can make things better. We move forward, onwards, and upwards — to the next project, ticket, and feature release. We code tirelessly, recycling what we know to make the things we need to work, well, work.

Over the years, I’ve picked up a few things here and there. Here are my top 7 little big JavaScript techniques that make code look better, feel better, and read better.


1. The … spread operator

It turns out that the spread ... operator is still making its round in the new-to-JavaScript circles. It’s just one of those things that can be easily missed when picking JavaScript.

What is a spread operator? How does it work? Here’s a quick walkthrough.

You have an iterable that needs to be placed inside an array. However, you don’t know the final length of this iterable — or you just can’t be bothered writing it all out manually.

This is where the spread ... operator comes in.

It automatically places the iterable inside an array for you.

Here’s some code to help you make sense of it:

let abc = ['apple', 'bananas', 'cherries', 'dragon fruit'];
let abc_spread = [...abc]
console.log(abc_spread);
// this will return:
// ['apple', 'bananas', 'cherries', 'dragon fruit'];

Let’s take a look at another example:

const PREFIX = '$';
let message = '$kick ivan89234 bot0298 fake122  ';
function kick(){
  
  const [CMD_NAME, ...args] = message
         .trim()
         .substring(PREFIX.length)
         .split(/\s+/);
  
 console.log(CMD_NAME);
 console.log(args);
  
  
}
kick();
// console.log() will return
// "kick"
// ["ivan89234", "bot0298", "fake122"]

Using the spread operator is much easier, more efficient, and less cumbersome to code than trying to loop through everything and then manually placing it inside an array.


2. Recursions

A recursion is basically like a loop within a loop — but without the nesting. It calls itself indefinitely until the ‘escape’ clause is invoked.

Here is an example:

function weight(x, n){ 
  
   if(n == 1) return x; //the escape clause
    
   return x * weight(x, n -1); //the recursion
  
}
console.log('Tibbers weighs ' 
            + weight(2, 5) 
            + ' pounds after eating 5 pieces of cheese' );

The difference between a recursion and a loop is that recursions are self-contained and produce a specific output based on input. A loop runs linearly and demands each succession to be executed in order to produce a result.


3. Use log levels

There’s more to console.log than just console.log. Log levels make logging much easier on the eye and alert you to the things that are important. It also visually breaks up your logs in the console, making it easier to scan for the information you need.

Here’s the comprehensive list:

console.log("hello world")
console.warn("this is a warning")
console.error("this is an error")
console.info("this is info")
console.debug("this is debug")
console.trace("show trace")

Here’s what it actually looks like:


4. The language of boolean variables

Double negatives can be confusing. Keep things simple by always starting your boolean language assumption as true.

For example:

const isInvalidKey = apiKey === null
if(isInvalidKey){}

The above is a bad code language pattern because while seemingly straightforward, it gets confusing when you want to inverse it with !.

if(!isInvalidKey){}

Here’s a better way to write it:

const isValidKey = apiKey != null
if(!isValidKey){}

No one likes reading double negatives in general because you’re forced to compute what the expected outcome is. It’s not a simple yes or no answer anymore once you start using negatives to describe a boolean.


5. Objects instead of argument lists

The thing with argument lists is that they have to be in a specific order. However, if you use objects, it’s easier to pass in optional parameters and the order doesn’t matter anymore.

It’s also easier to read and understand what you’re passing in through an object than it is for a list of argument variables.

Here’s an example:

function getItem(price, quantity, name, description) {}

getItem(15, undefined, 'bananas', 'fruit')

Here’s the refactored version:

function getItem(args) {
    const {price, quantity, name, description} = args
}

getItem({
    name: 'bananas',
    price: 10,
    quantity: 1, 
    description: 'fruit
})

6. Return over if/else

if/else statements are great — until they aren’t. There are too many unnecessary curly braces {} all over the place.

In most cases, if/else statements aren’t needed if a return does exactly the same job.

Here’s what I mean. Take a look at the following example:

function someCode(){    
   if(someBoolean){ 
      return something; 
  }else{ 
      return anotherthing; 
  }
}

In reality, this will also have the same impact:

function someCode(){    
   if(someBoolean){ 
      return something; 
  }
   return anotherthing; 
  
}

The point of having return is to end the program. Writing the else statement becomes redundant if the if condition is not fulfilled anyway.


7. Catch errors before everything else

We all make the mistake of thinking that everything will be well and dandy. But over the years, I find that the more pessimistic your code is towards conditions not being fulfilled, the less prone it is to bugs.

Why?

Because the condition returned may work but also silently fail your errors.

Here’s what I mean. Take a look at the following example:

'use strict';
...
const fakeAPI = function(callback){
    request(`https://someapi.com/api`, 
            {json: true}, 
            (err, res, body) => {
          if(res){
                    //do something
                }else{
                    callback(err)
                }
    })
}

You’re assuming that your API will work all the time. It might have thrown an error and given back a res and we would never know about the err.

Here’s a different way to look at the same code:

'use strict';
...
const fakeAPI = function(callback){
    request(`https://somesite.com/api`, 
            {json: true}, 
            (err, res, body) => {
          if(err) return callback(err)
          //rest of your code to deal with res
    })
}

You’re always assuming the worst — so you put your errors in first so it never fails in silence.


Wrap up

These are my favorite and top 7 techniques that I often advocate and talk about to developers when it comes to JavaScript. It’s not everything but a good starting point, especially when you are refactoring code or working on making your code easier to read and maintain.