And how ‘`let’` solves a common JavaScript “gotcha”… ----------------------------------------------------  I’ve been writing JavaScript using the ES2015 (ES6) syntax for awhile now and have grown to appreciate many of the language changes for their elegance and simplicity. One of the first and easiest changes I adapted to was using `let`/`const` instead of `var`. However, I took for granted the benefit `let` provides over `var`; it isn’t just a flashy new syntax for `var`, but rather provides an important scoping mechanism. > I took for granted the benefit `let` provides over `var...` It’s worth noting first that _the vast majority of variables I declare are best suited for using_ `_const_` instead of `let`/`var`. This is because `const` will throw an error if an attempt is made to change its value after it has been declared, a useful feature to prevent accidental mutation. However, a mutable variable is often needed, particularly as a counter in looping scenarios. But why should you use `let` instead of `var` for these situations, if they both provide the basic mutability required of them? The simple answer is that `**let**` **provides block-scoping** that is absent in the function-scoped `var`. This explanation obviously begs a practical example. Allow me to demonstrate this important distinction using a classic front-end engineering interview question: In this example, what will be printed in the console? var callbacks = \[\]; (function() { for (var i = 0; i < 5; i++) { callbacks.push( function() { return i; } ); } })(); console.log(callbacks.map( function(cb) { return cb(); } )); In this example, we loop 5 times, each time pushing a function into the `callback` array. After the array is filled with 5 functions, we run each of them, logging their result to the console. A novice engineer might answer (incorrectly) that the result is `[0, 1, 2, 3, 4]`, _a reasonable analysis, but one that falls victim to the JavaScript “hoisting” gotcha_.  Don’t be a victim. Avoid the hoisting trap with ‘let’! The correct answer is actually `[5, 5, 5, 5, 5]`, and makes sense when you consider what hoisting does behind the scenes: var callbacks = \[\]; (function() { **var i;** for (**i** = 0; i < 5; i++) { callbacks.push( function() { return i; } ); } })(); console.log(callbacks.map( function(cb) { return cb(); } )); Notice how JavaScript hoists the variable declaration to the top of the function block, causing the value of `i` to be `5` by the time each of the callback functions have executed, since the `for` loop has incremented completely before any of these functions are called. There are a number of ways to classically solve this problem and get the script to log `[0, 1, 2, 3, 4]` to the console, but `let` gives us a very simple solution: var callbacks = \[\]; (function() { for (**let** i = 0; i < 5; i++) { callbacks.push( function() { return i; } ); } })(); console.log(callbacks.map( function(cb) { return cb(); } )); That’s it — **just replace** `**var**` **with** `**let**` and the example works as expected! This is thanks to the block-scoping behavior of `let`. Rather than being hoisted to the top of the function’s scope, `_let_` _stays in the block scope of the loop_, causing a separate instance of `i` for each iteration. So, should you ever use `var`? As you have likely gathered from the title of this article, I am of the opinion that **you should never use** `**var**`. Technically, `var` is still useful in situations where you want to maintain function scope instead of block scope, but I am of the firm belief that if you need to rely on an unintuitive hoist to get your script to work, you have bigger problems 😜. **Update:** In response to two of the most common points of discussion readers are bringing up: 1. It is true that `const` isn’t _truly_ immutable. For instance: const myNotQuiteImmutableObject = { thisCanBeChanged: "not immutable" }; myNotQuiteImmutableObject.thisCanBeChanged = "see I changed it."; However, this still prevents basic mutation like: const immutableString = "you can't change me"; immutableString = "D'OH!"; // error If you need real immutability, check out Facebook’s excellent [Immutable](https://facebook.github.io/immutable-js/) library. 2\. “`let` isn’t supported in `{mySuperAncientBrowser}`.” This is true, and even [somewhat recent browsers still don’t have support for](http://caniuse.com/#feat=let) `[let](http://caniuse.com/#feat=let)`. This has an obvious and easy solution: Use [Babel](https://babeljs.io/). Babel will allow you to use all the best and latest features of JavaScript and then transpile into a vocabulary that even simple old IE8 can understand (with some exceptions).