let
var
Variables in JavaScript are function scoped. This is different from many other languages (C# / Java etc.) where the variables are block scoped. If you bring a block scoped mindset to JavaScript, you would expect the following to print 123
, instead it will print 456
:
This is because {
does not create a new variable scope. The variable foo
is the same inside the if block as it is outside the if block. This is a common source of errors in JavaScript programming. This is why TypeScript (and ES6) introduces the let
keyword to allow you to define variables with true block scope. That is if you use let
instead of var
you get a true unique element disconnected from what you might have defined outside the scope. The same example is demonstrated with let
:
Another place where let
would save you from errors is loops.
In all sincerity we find it better to use let
whenever possible as it leads to fewer surprises for new and existing multi-lingual developers.
Functions create a new scope
Since we mentioned it, we'd like to demonstrate that functions create a new variable scope in JavaScript. Consider the following:
This behaves as you would expect. Without this it would be very difficult to write code in JavaScript.
Generated JS
The JS generated by TypeScript is simple renaming of the let
variable if a similar name already exists in the surrounding scope. E.g. the following is generated as is with a simple replacement of let
with var
:
However, if the variable name is already taken by the surrounding scope then a new variable name is generated as shown (notice foo_1
):
Switch
You can wrap your case
bodies in {}
to reuse variable names reliably in different case
statement as shown below:
let in closures
A common programming interview question for a JavaScript developer is what is the log of this simple file:
One would have expected it to be 0,1,2
. Surprisingly it is going to be 3
for all three functions. Reason is that all three functions are using the variable i
from the outer scope and at the time we execute them (in the second loop) the value of i
will be 3
(that's the termination condition for the first loop).
A fix would be to create a new variable in each loop specific to that loop iteration. As we've learnt before we can create a new variable scope by creating a new function and immediately executing it (i.e. the IIFE pattern from classes (function() { /* body */ })();
) as shown below:
Here the functions close over (hence called a closure
) the local variable (conveniently named local
) and use that instead of the loop variable i
.
Note that closures come with a performance impact (they need to store the surrounding state).
The ES6 let
keyword in a loop would have the same behavior as the previous example:
Using a let
instead of var
creates a variable i
unique to each loop iteration.
Summary
let
is extremely useful to have for the vast majority of code. It can greatly enhance your code readability and decrease the chance of a programming error.
Last updated