More articles

How to use block bindings in ES6

Written by
Published on
Modified on

For a long time now, declaring variables using the standard var keyword was commonplace in JavaScript. While super easy to use, it was not without its limitations. For one, it created an issue with 'hoisting'. Any variable declared within a function, or within the global score, was 'hoisted' up to the top of function (or global scope). Which meant that variables within smaller code-blocks, such as if-else statements or for loops, were not actually local to those blocks.

function func1()
{
    for (let i = 0; i < 10; i++)
    {
        var tmp = 10;
    }

    console.log(tmp);    // still works
}

Take this as an example. In this case, the tmp variable is actually still available to be used outside of the for loop, even if that was not an intent that we had in mind. This was something that we normally just had to deal with as developers in the past.

Block level declarations

The new ES6 specification allows for block-level variable declarations by introducing the new 'let' and 'const' identifiers. You might also see block scopes also referred to as 'lexical scopes'.

These block-level scopes can be created either inside of a function, or inside of any code block, such as with an if-else statement or for loop.

'let' declarations

The let declaration gives us true 'block-level' scope for our variables for the first time.

function func1()
{
    for (let i = 0; i < 10; i++)
    {
        let tmp = 10;
    }

    console.log(tmp);    // would result in an error
}

The tmp variable in this case only belongs to the for loop and can only be used within that scope. This behavior is more what we would actually expect it to behave like in other programming languages.

Note: This does not mean go out and replace every single var that you see with a let. Most of the internet was probably written during a time before the ES6 specification, which means some code will be structured to work with var's 'hoisting' capabilities in mind. Changing this behavior could lead to unexpected behavior, such as you breaking production.

'const' declarations

We also now have the 'const' declaration to further restrict how variables are treated and modified. With the 'const' declaration, variables can not be modified once they have been initialized. This is ideal for static values, such as Pi or for any other constants that you know for a fact can not be changed.

Note that you have to initialize a 'const' variable with some form of value. Not doing so will throw an error.

const pi = 3.14;

pi = 5; // error

Constant variables are treated as 'block-level' variables similar to variables declared using 'let'. Some would argue that every variable should be declared as a 'const' and only changed otherwise if the code requires it to be so. In this case you reduce the chance of unexpected variable updates. There could definitely be something to that approach.

Objects and 'const'

There is one thing to make note of when using the 'const' declaration with JavaScript objects. While you cannot modify the variable object itself, you can modify the objects properties.

const car = {
    make: 'Honda',
    model: 'Fit'
};

car.year = '2018';    // this is valid

Note that this includes adding new properties to the object as well.

Loops and block-level declarations

Many developers never realized that for-loop declarations were one of the areas that required block-level variable declarations the most. Take the following for example:

for (var i = 0; i < 10; i++)
{
    // code goes here
}

console.log(i);   // still works!

In this case, the 'i' variable is still accessible outside of the for loop! Which pollutes our variable namespace in the long term. This could also have issues if you had multiple for loops in a given function, in which case you would end up re-declaring the 'i' variable, which might not be the intended effect.

for (let i = 0; i < 10; i++)
{

}

console.log(i);    // error!

Loops and 'const' declarations

While you are free to declare a 'const' inside of a for loop initializer, if the variable is at all modified, it will throw an error.

for (const i = 0; i < 5; i++)
{
    // will only run one time before error
}

If however, you choose a function that does not modify the initializer, such as a for-in loop, then you are just fine.

var car = {
    make: 'Honda',
    model: 'Fit'
};

for (const key in car){
    console.log(key);    // totally fine
}

Summary

Block-bindings allow for cleaner and more scalable code and is the default behavior for many of today's programming languages. It's a great addition to the JavaScript language, and while the adoption rate is a slow process, the best time to start using these concepts is today.

Walter G. is a software engineer, startup co-founder, former CTO of several tech companies and currently teaches programming for a coding bootcamp. He has been blogging for the past 5 years and is an avid BMX rider, bio-hacker and performance enthusiast.
If you read this far, then I hope you enjoyed this post and found it useful! Consider adding to my daily coffee intake to continue to provide better and more helpful articles in the future!
Maybe later

Discussion / Comments / Questions

No messages posted yet

Add a comment

Send me your weekly newsletter filled with awesome ideas
Post comment