Categories
JavaScript Best Practices

JavaScript Best Practices- Variable Declarations, IIFEs, and Yoda

Spread the love

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we look at why we should put var declarations on top, wrapping IIFES, and Yoda expressions.

Put Variable Declarations to be at the Top of Their Scope

We should put variable declarations on the top of their scope so that we’re sure that we can access them from the beginning.

One confusing feature of JavaScript is that variables declared with var can be hoisted.

The declaration is hoisted but the value assigned to it is not.

For instance, if we have:

console.log(x)
var x = 1;

Then we should see that x is undefined from the console log output because the var x part is hoisted to the top, but setting the value is still done after the console log call.

var is function scoped, so it’s fine for it to be declared on top of a function block.

But they should all be declared before any code inside is run. So, we shouldn’t have code like:

function foo() {
  var first;
  first = 1;
  var second;
}

In the code above, the second variable is written after the first = 1; expression, so second will be hoisted to the top of the function.

If we log it as follows:

function foo() {
  var first;
  console.log(second);
  first = 1;
  var second = 2;
}

foo()

Then we get that second is undefined since var second is hoisted to the top, but the rest of the expression stays at the bottom.

As we can see, having var variables below the top section of a function or at the top level of a script is a pain. We’ve to know that some part of it is hoisted.

Therefore, we should just put all of the var declarations at the top. If it’s a script, we should put var declarations at the top of the top-level of a script as follows:

var foo = 1;
var bar = 2;
//...

Then we don’t have to worry about hoisting.

Likewise, in functions, we should put all the var declarations on top as follows:

function baz() {
  var foo = 1;
  var bar = 2;
  //...
}

It’s just painful to have them anywhere else. Better yet, we should use let and const instead of var . They’re block-scoped and they aren’t hoisted so that they can only be referenced after they’re defined.

Wrap Our IIFEs

IIFEs are immediately invoked function expressions. They’re functions that are called immediately after they’re declared.

We should wrap them to make sure that we’re calling the function and avoid syntax errors.

For instance, if we have the following code:

const bar = () => ({
  a: 1
})();

The () in the end, we didn’t call the arrow function we declared. And if we log bar , we just get the function itself.

Instead, we should write:

const bar = (() => ({
  a: 1
}))()

The code above wraps the whole function in parentheses. Then when we add the () after it, the function we defined is actually called.

If we want to call a function method like bind , call , and apply right after the function is defined, we can do the following:

const x = (function() {
  return this
}).call({
  a: 1
})

This way, call actually is called on the function we defined.

Therefore, we should always wrap our IIFEs with parentheses so that it’ll be called if we add () after it.

No Yoda Conditions

A condition expression like the following:

if ("apple" === fruit) {
  _// ..._
}

is called a Yoda condition because it reads like ‘if apple equals the fruit’, which like how Yoda in Star Wars speaks.

If we flip the operands in the condition as follows:

if (fruit === "apple") {
  _// ..._
}

Then the condition reads like ‘if the fruit equals apple’, which is more natural for many people.

This is more of a style preference since we may be able to use the = operator instead of === to assign 'apple' to fruit instead of comparing them with the === operator.

But it reads more naturally, so it’s a matter of preference rather than something we should change.

Conclusion

Yoda expressions are things like "apple" === fruit . It’s more of a matter of preference in how we order the operands.

IIFEs should always be wrapped with parentheses so that we make sure it’s always called.

var declarations should always be on top of their scope so that there’s no ambiguity with hoisting.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published.