Bitsy Explains
Home/JavaScript, Explained Like You're Five/Lesson 3

var vs let in JavaScript

var is the old way to make variables. It leaks out of blocks, lets you declare a name twice and gives undefined when used too early. Use const or let instead.

Lesson 3 of 203 min readVideo
Video thumbnail: var vs let Watch the 90-second video
Explain like I'm five

In the let video, let was a whiteboard. Picture it hanging inside one room, and the walls of that room are the curly braces. A var whiteboard ignores the walls. Write on it inside the room, and everyone outside can see it too.

Why var acts differently

var is older than block scope. It only respects the walls of a function. The braces of an if, a for loop or a plain block don't hold it in. let and const arrived in 2015 to fix that.

function makeSnack() {
  var fruit = "apple";
  return fruit;
}
console.log(makeSnack()); // prints: apple
console.log(typeof fruit); // prints: undefined

Here the function walls do their job. fruit exists inside makeSnack, and outside it there's no such name (typeof reports "undefined" for a name that was never made). Every other kind of curly brace is see-through to var.

It leaks out of blocks

if (true) {
  var color = "teal";
}
console.log(color); // prints: teal

The variable was made inside the if block, but you can still use it outside. With let, that last line would throw ReferenceError: color is not defined.

An error sounds bad, but here it helps you. It tells you right away that you used the variable in the wrong place, instead of letting the bug hide.

Leaking shows up a lot in loops. A var loop counter is still hanging around after the loop ends.

for (var i = 0; i < 3; i++) {}
console.log(i); // prints: 3

It lets you declare a name twice

var name = "Bitsy";
var name = "Bob";
console.log(name); // prints: Bob

No warning at all. The second line just replaces the first. In a long file, that's an easy way to overwrite something you still needed.

let and const refuse with SyntaxError: Identifier 'name' has already been declared. That name is taken.

The twist: hoisting

Hoisting means lifted to the top. Before your code runs, JavaScript sets up every var name at the top of its function (or file), but leaves the value behind on its own line. So if you use a var too early, you don't get an error. You get undefined.

console.log(cookie); // prints: undefined
var cookie = "yum";
console.log(cookie); // prints: yum

let and const are hoisted too, but they stay locked until their line runs. Touch one before that and you get ReferenceError: Cannot access 'cookie' before initialization. That error catches the bug early, which is what you want.

What to use instead

In new code, use const. If the value has to change, use let. You will still see var in older tutorials, libraries and answers online, so it helps to recognize it, but you don't need to write it yourself.

When you copy an old example that uses var, change it as you paste it in. Most of the time const works straight away. If JavaScript then complains that you assigned to a constant, switch that one to let.

Rule of thumb

Don't use var. Use const, or let when the value changes.

Common mistake

Swapping every var for let in old code without looking. If the code relied on a variable leaking out of a block, the swap turns it into a ReferenceError. Move the declaration above the block first, then change it to let or const.

Check yourself

What does this print? console.log(snack); var snack = "apple";