Take a look at the following code:
// define some fruitsvar orange = 'orange'; var apple = 'red';
if (orange === 'orange') { var orange = 'blue'; // the scope is global let apple = 'green'; // the scope is inside the if-block console.log(orange); // blue console.log(apple); // green} console.log(orange); // blueconsole.log(apple); // red
When programming in in Javascript, you need to declare variables to hold data that you will need to access later for use in your program. You have two means to choose from in order to achieve that goal.
You can define your variable using var
or let
. The outputs of the above code is a good introduction to the differences between those two keywords but let’s dive in for a deeper understanding of their differences and why one is better than the other.
An orange should never be blue. If yours is throw it out.
The differences between the two are subtle but important. Failing to understand the differences may cost you minutes or even hours of debugging a silly error in your program that is otherwise error free. In the remainder of this article, you will learn the fundamental difference between these two means of defining a variable as we break down the above code.
First, an assertion. This is only an opion, but it is regarded as a best practice by most programmers that I’ve encountered as well as the The World Wide Web Consortium (W3C), the “international community that develops open standardst o ensure the long-term growth of the Web”. Why? Well, this is what the W3C says about globals:
Global variables and function names are an incredibly bad idea. The reason is that every JavaScript file included in the page [or program] runs in the same scope. If you have global variables or functions in your code, scripts included after yours that contain the same variable and function names will overwrite your variables/functions.
Furthermore, it’s just not classy. You want to be classy, right?
There are many ways to avoid introducing global variables in you program. Some of the approaches you can take to avoid globals require an non-insignificant amount of thought, but others are simple. Let’s start simple.
One of the simplest ways to move yourself in the right direction away from globals is to stop using var
now. Yep, just drop it. When you’re done reading this article, it would behoove you to go replace all usage of var
in your programs to let
. It may cause some errors or unexpected behavior for reasons you will begin to understand below, but in the end, your code will be happier.
Before we learn about let
, lets take a look at var
. When you define a variable with var
, the scope of that variable will be its enclosing execution context; that execution context can be either a function space or the global space.
{var salutation = 'hi';
console.log(salutation); // hiconsole.log(this.salutation); // hi
function runModule() {var salutation = 'hola';if (1 == 1) {console.log(salutation); // hola}}
runModule();
console.log(salutation); // hi
if (1 == 1) {var salutation = 'cheers';console.log(salutation) // cheers
if (2 == 2) {
var salutation = 'cheers again'
console.log(salutation) // cheers again
}
console.log(salutation) // cheers again
}
console.log(salutation); // cheers again
salutation = 'bye'
console.log(salutation); // byeconsole.log(this.salutation); // bye}
In the code above,
this
is the global or top level namespace. Unfortunately, our variable is created on it.
The code immediately above is a good example of how variables defined with var
are scoped. Notice that the saluation
variable defined in the runModule()
method is scoped to that method and does not escape it. That’s great. However, take a look at the saluation
variable defined in the if
statement using var
; it clashes with the initial salutation
variable that is defined at the top of that code block. Why? Because both variables are declared in the global scope and are not enclosed in a function block. The var
keyword does not do anything to stop these two declarations from clashing. You could simply use a different name for the second variable in the if
block, but sometimes you just need to reuse a variable name. Enter let
.
Here’s why the let
keyword is the better way to declare your variables: unlike var
it does not create a property on the global object regardless of where you define it. Wait, there’s more!
When you declare a variable by let
that variable’s scope will be the block in which it is declare. The block can be that of a function, if
statement, switch
statement, while
statement, or any other block that exists in javascript. That all means that the value of a variable defined by let
will not escape the block that it is declared in. This is wonderful because it solves the problem I noted at the end of the var
section above. Let’s see the same example from above
{let salutation = 'hi';
console.log(salutation); // hiconsole.log(this.saluation); // undefined
function runModule() {let salutation = 'hola';if (1 == 1) {console.log(salutation); // hola}}
runModule();
console.log(salutation); // hi
if (1 == 1) {let salutation = 'cheers';console.log(salutation) // cheers
if (2 == 2) {
let salutation = 'cheers again'
console.log(salutation) // cheers again
}
console.log(salutation) // cheers
}
console.log(salutation); // hi
salutation = 'bye'
console.log(salutation); // byeconsole.log(this.salutation); // undefined}
Do you see the difference? With let
, the salutation variable is scoped strictly to the block it is declared in. If two variables with the same name are declared with the second being in a sub-scope of the scope that the first, the sub-scoped variable will not override the value of the parent scope variable; this is evident in the second and third if
statements in the above code. Also, as noted earlier, the salutation
variable defined with let
, unlike that created with var
, does not create a property on the global object; that’s why console.log(this.salutation)
prints undefined
.
One thing you should try on your own: redeclare a variable using var
and observer that nothing breaks when it should; do the same with let
and a SyntaxError
will be thrown as it should. The latter is the desired behavior if you are a sane person who doesn’t enjoy looking for a bug in a haystack.
There you have it. Go forth and rid yourself and your Javascript code of the var
keyword. There’s more nuance, so be sure to check out Mozilla’s rundown of it all.
Lincoln W Daniel is the creator of Smedian, Editor in Chief of Mark Growth’s Marketing & Growth Hacking publication, and author of Java for Humans.
You’re invited to chat with me on Smedian.