Categories
JavaScript Best Practices

Better JavaScript — Defining Functions

Spread the love

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at ways to improve our JavaScript code.

Use Immediately Invoked Function Expressions to Create Local Scope

Immediately Invoked Function Expressions or IIFEs for short, are functions that are created and called immediately.

For instance, we can create one by writing:

(function(){})();

We create the function and we can put whatever want to keep private inside.

It was used to get around JavaScript’s lack of block-scoped variables before ES6.

But now we need this less because we have modules to keep things private.

And we can define block-scoped variables with let and const .

If we use it in a block, then we may see some issues.

For instance, if we have a loop like:

function foo(a) {
  var result = [];
  for (var i = 0; i < a.length; i++) {
    (function(j) {
      result[i] = () => a[j]
    })(i);
  }
  return result;
}

Then we can’t use break or continue in the IIFE.

The this inside the IIFE would also change because of the traditional function used for the IIFE.

So we can do away with the IIFE, we change the var s th let and remove the IIFE:

function wrapElements(a) {
  let result = [];
  for (let i = 0; i < a.length; i++) {
    result[i] = () => a[i]
  }
  return result;
}

Since let is block-scoped the value of i will update and passed into the arrow function we set for result[i] in each iteration.

Unportable Scoping of Named Function Expressions

The meaning of the function can change depending on the context even though the function’s code looks the same.

For instance, if we have:

function times(x) {
  return x * 5;
}

then that’s a function declaration.

On the other hand, if we have:

const times = function(x) {
  return x * 5;
}

then that’s a function expression.

A function expression is where we define with the function keyword and didn’t assign that to a variable.

If we assign that to a variable, then it becomes a function expression.

We can also write:

const f = function times(x) {
  return x * 5;
}

to define a function expression

The difference between anonymous and named function expression is that the latter binds its name to the local variable within a function.

For instance, we can write:

const traverse = function find(tree, key) {
  if (!tree) {
    return null;
  }
  if (tree.key === key) {
    return tree.value;
  }
  return find(tree.left, key) ||
    find(tree.right, key);
};

We call find in the find function.

But when we call it outside, we call it with traverse .

Since we can just call traverse to do the same thing, having a name in the function’s scope isn’t very useful.

We can also use a function declaration like:

function find(tree, key) {
  if (!tree) {
    return null;
  }
  if (tree.key === key) {
    return tree.value;
  }
  return find(tree.left, key) ||
    find(tree.right, key);
}

However, named function expressions are useful for debugging.,

Most modern JavaScript environments produce stack traces with Error instances and the name will be used for the stack trace.

Conclusion

IIFEs have some uses but not as much as before.

Also, there’re several ways to define a function and they do slightly different things.

By John Au-Yeung

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

Leave a Reply

Your email address will not be published. Required fields are marked *