Categories
JavaScript

Good Parts of JavaScript — Recursion and Scope

Spread the love

JavaScript is one of the most popular programming languages in the world. It can do a lot and have some features that are ahead of many other languages.

In this article, we’ll look at ways to make a function call itself and scopes of functions.

Recursion

A recursive function is a function that calls itself.

We can use it do divide a problem into a set of subproblems, each with a trivial solution.

For instance, we can create a recursive function as follows:

const count = (i) => {
  if (i === 10) {
    return;
  }
  console.log(i);
  count(i + 1);
}

count(0);

In the code above, we have a simple recursive function that stops with i reaches 10.

For each value of i , we log the value of i to the console.

We should make sure that we have a base case to stop the function.

If a function returns the result of running itself recursively, JavaScript doesn’t optimize that by replacing it with a loop.

For instance, if we have:

const factorial = (i, a = 1) => {
  if (i < 2) {
    return a;
  }
  return factorial(i - 1, a * i)
}

const result = factorial(10);

Then JavaScript will turn that into a loop, so the call stack would be full if we call it too many times.

Scope

Scope in a programming language controls the visibility of variables and parameters.

In JavaScript, we have a function and block-scoped variables.

let and const are block-scoped and var is function-scoped.

Therefore, to reduce confusion, we should use let and const to declare data.

For instance, if we have:

if (condition) {
  let x = 1;
  const y = 2;
  //...
}

x and y are block-scoped, so they’re only available within the if blocks.

We should just forget about var and use let or const exclusively.

Variables should be declared as late as possible so that their lifetimes are short.

This reduces the need to follow the use of variables through many lines of code when we’re reading code.

Closure

Inner functions get access to parameters and variables of functions that are defined in.

We can use this to make values private and use them in inner functions.

For instance, we can write:

const obj = (() => {
  let value = 0;
  return {
    increment(val) {
      value += val;
    },
    getValue() {
      return value;
    }
  };
})();

value is private, so that we can update value by incrementing it with val .

So we update value safely without exposing them to the outside.

We used an IIFE above, we can return an object that uses private variables.

Also, we can turn that into a factory function by removing the parentheses.

For instance, we can write:

const createName = (name) => {
  return {
    getName() {
      return name;
    }
  };
};

const name = createName('foo').getName();

We return an object that returns the value of the name parameter.

It’s not a constructor so that we can’t use it with the new operator.

Inner functions have access to the variable itself rather than the value when it’s made.

For instance, if we have:

const addHandlers = (nodes) => {
  for (var i = 0; i < nodes.length; i += 1) {
    nodes[i].onclick = () => {
      alert(i);
    }
  }
}

addHandlers(document.querySelectorAll('button'))

If we run the code above, the alert box always shows 3 no matter which button we click.

This is because the loop body is found to the variable i rather than the variable i at the time the function is made.

To fix this, we can use let instead of var :

const addHandlers = (nodes) => {
  for (let i = 0; i < nodes.length; i += 1) {
    nodes[i].onclick = () => {
      alert(i);
    }
  }
}

addHandlers(document.querySelectorAll('button'))

let is block-scoped so that the onclick handler will get the current value of i rather than the value of i when the loop is done.

Conclusion

Recursive functions are functions that call themselves directly or indirectly.

It’s useful for dividing problems into trivial subproblems.

Scopes of variables depends on how we declare them. If we declare them with let or const , then they’re block-scoped.

If we declare them with var , then they’re function-scoped.

Closures allows us to access private variables.

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 *