let var be const

K - Dec 12 '17 - - Dev Community

Cover image by Christiaan Colen on Flickr

With ES2015 JavaScript got a bunch of new features, two of them being let and const keywords that let you declare your local variables.

var

Variables you declare with var will be scoped to the function they were declared in.

This means, even if you declare them in nested blocks (other curly braces) inside of a function, they will still be scoped to the function.

For example, if you declare it inside of a try block like this:

    function f(x) {
      try {
        var y = x.toString();
      } catch(e) {
        return "";
      }
      return y;
    }
Enter fullscreen mode Exit fullscreen mode

It will actually be declared like that:

    function f(x) {
      var y;
      try {
        y = x.toString();
      } catch(e) {
        return "";
      }
      return y;
    }
Enter fullscreen mode Exit fullscreen mode

Every var declaration will be hoisted to the top of the function. This is why it is considered a best practice to declare vars at the top of a function, it will end up there anyway.

If you want to scope a var to a code block, you would have to fill or replace it with a function expression and call the function right after definition.

    function f(x) {
      var y;
      if (x >= 0) (function() {
        var z = Math.random() * 10;
        y = x * z;
      })();
      return y;
    }
Enter fullscreen mode Exit fullscreen mode

The anonymous function has access to f()s local variables, so it can use y, but z is only defined inside of the anoynmous function and can't be accessed inside f().

As you can see, this is rather sub-optimal, but this was the way for many years. If you are bound to use ES5 and for some reason can't use a compiler like Babel, you still have to do this.

let

The let keyword is now a way to declare variables that aren't scoped to a function, but to a block. This means any code enclosed by curly braces confines that variable.

    function f(x) {
      let y;
      if (x >= 0){
        let z = Math.random() * 10;
        y = x * z;
      } else {
        y = 10;
      }
      return y;
    }
Enter fullscreen mode Exit fullscreen mode

In this example z is only accessible inside the if-branch, the else branch or the rest of f() could not access it.

Blocks can alse be used without any statement.

    function f(x) {
      let results = [];

      // first calculations
      {
        let a = 10 * 10 * x;
        let b = a * Math.PI;
        results.push(b);
      }

      // second calculations
      {
        let a = 3 + 2 + x;
        let b = a * a;
        let c = a + b;
        results.push(c);
      }

      return results;
    }
Enter fullscreen mode Exit fullscreen mode

This allows to structure code and scope variables to the part of the function they are used. As you can see, the blocks have access to the outer scope variables results and x.

const

So what is the const keyword about? Well, you may have seen it in other languages like C or Java. In JavaScript it declares a variable that can't be changed, but be careful this only applies to the direct content of that variable. Otherwise it scopes as let.

This won't work:

    const a = 10;
    a = 11;
Enter fullscreen mode Exit fullscreen mode

These on the other hand will:

    const a = [1, 2, 3];
    a.push(4);

    const b = {x: 10, y: 20};
    b.z = 30;
Enter fullscreen mode Exit fullscreen mode

To prevent objects (arrays are objects too) from being changed, you need to freeze them manually, which impacts performance.

This will throw an error:

    const a = Object.freeze([1, 2, 3]);
    a.push(4);
Enter fullscreen mode Exit fullscreen mode

When Use What?!

I try to use const as much as possible, if functions get bigger, it often gets cumbersome to find out how often and where a variable was changed on the way down.

Sometimes it helps to use let with try/catch, because I have to set a variable inside try and it needs to be accessible after the try.

I avoid var completely nowadays. const and let have the same scoping, their only difference is their write-access, so it's easy to reason about them interchangably. var on the other hand works much different from them and I think it just makes stuff more complicated when mixed.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .