Lukasz Drazewski

personal blog

Let and const - how to use them

JS variables

There are three ways in JavaScript that one can declare a variable - var, let, and const. Before ECMAScript 2015 (ES6), we only had var declarations. Variables declared with var do not support block-level scope but are limited to function scope. It means that if a variable is declared with var in a loop or a block is also available outside the loop or if block. This is because they are hoisted. Variables declared with the var keyword always have a function scope, which means that they recognize functions as having a separate scope. Therefore, this local scope variable is not available with global scope. Let's see two examples:

function doSomething() {
    var foo = 'bar';

    return foo + foo;
}

console.log(foo) //Error: foo is not defined
function doSomethingWithX(x) {
    console.log(foo) // foo is undefined because is hoisted inside function scope
    if (x) {
        var foo = x;
    }

    console.log(foo); // "x" value
    return foo + 'bar';
}

Let and const

In ES6 we got two new ways to declare variables: let and const. Let and const differ significantly from the var declaration. First of all, they have a block, not a global scope, and they are not hoisted either. So let's see what the situation will look like for a let variable, for the example above:

function doSomethingWithX(x) {
    console.log(foo) //Error: foo is not defined
    if (x) {
        console.log(foo) //ReferenceError: can't access lexical declaration`X' before initialization
        let foo = x;

        console.log(foo) // x
    }

    console.log(foo); //Error: foo is not defined
    return foo + 'bar';
}

As you can see variable declared with let is only available inside if(){ ... } block and only after its declaration, not before.

Another important feature that distinguishes var from const and let is that it could be redeclared and const and let could not. The only difference between const and let is that one assigned value to a variable using const can not be reassigned with a new value.

And that's basically all you need to know about const and let variables. However, there are times when we want to use both types of variables and this is where problems sometimes arise.

Mix let and const when destructing

Destructuring is a convenient way to extract multiple values from data stored in (possibly nested) objects and arrays and it can be used in locations that receive data (such as the left-hand side of an assignment).

I remember one interesting case when I was still a very novice javascript developer related to mixing let nad const declarations. I wanted to use let instead of const, but eslint was throwing me the error:

"use const because this variable is never reassigned."

This is because let assumes that the variable value will be changed at some point of execution but it was not happening for some of these variables in my code.

In fact, I wanted to use const for some elements and let for others. Then, thanks to the kindness of a more experienced developer colleague, I got to know a method called elision. Elision allows you to use the "holes" syntax to omit array elements from destructuring:

const foo = ['a', 'b', 'c'];

let [a, b, c] = foo; //ESlint warning: use const because this variable is never reassigned

----

let [ a ] = foo;
const [, b, c] = foo;
// No warnings, a is decalred with let and b and c with const

If more than one trailing comma is used, an elision (or hole) is produced. An array with holes is called sparse (a dense array has no holes). 

There is one more very interesting way to solve the above problem. As you probably know, almost everything is an object in javascript. Certainly, arrays are also objects. Therefore, the destructuring example above can be written as follows:

let [a] = foo;
const {1: b, 2: c} = foo;

In general, the topic of destructuring in js is amazingly interesting and should be known by all developers working in this language. To all interested, I highly recommend a great source of knowledge with examples: Exploringjs.com.