No doubt, one of the more basic concepts to grasp in javascript is the difference between the three available variable declaration keywords, var, let and const. The three types of declarations are similar enough to cause some confusion. I will lay out a series of similar code fragments exploring the outcomes of using each of these keywords in an attempt to solidify the difference with concrete examples.

I encourage you to first try to figure out the output before looking at the answers below or running the code snippets.

A comparison:

Although var is still present in many code examples, and as such needs to be understood, let and const were meant to replace var. For a number of reasons they offer better control over your variables.

Scope

Let’s begin with scope. What will be printed with the following code using a var declared variable?

// example 1var dog = 'collie'
number = 5
if (number < 10 ){
console.log(`Block ${dog}`)
}
function bark(){
console.log(`Function ${dog} barks`)
}
bark()
console.log(`Global ${dog}`)

In this instance, because dog is declared ONLY globally, it will be referenced from within the code block (the if statement) and within the function (bark) and both will print as well as the global log:
'Block collie', 'Function collie barks', 'Global collie’
In fact, using let or const would render the same outcome.

Now let’s declare dog in both the code block and function:

// example 2var dog = 'collie'
number = 5
if (number < 10 ){
var dog = 'beagle'
console.log(`Block ${dog}`)
}
function bark(){
var dog = 'rat terrier'
console.log(`Function ${dog} barks`)
}
bark()
console.log(`Global ${dog}`)

Var is function scoped, not block scoped. When dog is declared in the block, it wipes out the original ‘collie’ declaration and dog becomes ‘beagle’ in the global scope. However, inside the function, the declaration of dog to ‘rat terrier’ has its own scope that doesn’t effect the global (now ‘beagle’).

'Block beagle', 'Function rat terrier barks', 'Global beagle'

What will happen if we replace var with let or const in all of the ‘dog’ declarations in example 2 above?

Because let and const are block scoped (including functions), now each declaration has its own scope and the global ‘collie’ is unchanged:

'Block beagle', 'Function rat terrier barks', 'Global collie'

With var there is the danger of inadvertently re-assigning a global variable within a code block, something that won’t happen with var. Look at this next example:

number = 5if (number < 10 ){
var dog = 'beagle'
console.log(`Block ${dog}`)
}
console.log(`Global ${dog}`)

Above, the final log gets its value ‘beagle’ from with the if block, because var is function scoped.
'Block beagle', 'Global beagle'
Using let would (block scoped) would keep dog scoped inside of the if block and there would be an ‘undefined variable’ error for the second log.

Window object

In a browser the window object is the window of the browser, the top structure in the HTML tree. Variables declared with var globally are attached to the window object. Type var dog = ‘bowser’ in the browser’s console and then type window.dog. The value ‘bowser’ appears! This makes controlling the scope of the variable even more difficult. By contrast, let and const are not attached to the window object.

Assignment

Now let’s see what happens if we try to reference a variable that is declared after it is referenced:

console.log(dog)
var dog = 'collie'

You’ll notice that dog is hoisted to the top of the execution context (the order the code is processed), and is assigned the value of ‘undefined’. There is no error thrown. When we try the same with let (and const) the variable is also hoisted to the top but not assigned any value which throws an error:

Uncaught ReferenceError: Cannot access ‘dog’ before initialization

What happens when we declare but don’t initialize a variable:

let cat;
console.log(cat);

The above code using let will log undefined (the same as if you used var). Using const will result in an uninitialized error. Const variables need to be initialized when declared.

const cat;
console.log(cat);

Redeclaration

What will the following output?

var dog = 'collie'
console.log(dog)
var dog = 'beagle'
console.log(dog)

var variables can be redeclared within the same block:

'collie', 'beagle'

If we were to try the same code with let or const, the code would produce an error since neither can be reassigned within the same block. Once again, let and const provide more rigorous checks.

Reassignment

How do var and let handle reassignment?

let dog = 'collie'
console.log(dog)
dog = 'beagle'
console.log(dog)

We see that the variables can be reassigned with let (and var):

'collie', 'beagle'

What if we run the above code using const? We find that the reassignment (within the same scope) throws and error:

Uncaught TypeError: Assignment to constant variable.

The same will happen if we try to reassign the const dog declared at the global level, within a block or function since the scope of those blocks fall within the global scope as well.

Exception!

const cat = {name: 'tiger', type: 'tabby'}
console.log(cat);
cat.name = 'lion'
console.log(cat);

In this example we are not actually reassigning the value of cat, but rather reassigning what values the object references. We are allowed to change the key of ‘name’s value from ‘tiger’ to ‘lion

Takeaways

In general const should always be used unless there is a need to change the value of the variable (i.e. the index of a loop). In any other situation let should be used. It’s always best practice to initialize your variables when they are declared.

After years of teaching music in Austin, Shanghai and Yangon, I’m making a career change to my other passion, software development.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store