What are the differences between JavaScript variables created using `let`, `var` or `const`?
TL;DR
In JavaScript, let, var, and const are all keywords used to declare variables, but they differ significantly in terms of scope, initialization rules, whether they can be redeclared or reassigned and the behavior when they are accessed before declaration:
| Behavior | var | let | const |
|---|---|---|---|
| Scope | Function or Global | Block | Block |
| Initialization | Optional | Optional | Required |
| Redeclaration | Yes | No | No |
| Reassignment | Yes | Yes | No |
| Accessing before declaration | undefined | ReferenceError | ReferenceError |
Differences in behavior
Let's look at the difference in behavior between var, let, and const.
Scope
Variables declared using the var keyword are scoped to the function in which they are created, or if created outside of any function, to the global object. let and const are block scoped, meaning they are only accessible within the nearest set of curly braces (function, if-else block, or for-loop).
function foo() {// All variables are accessible within functions.var bar = 1;let baz = 2;const qux = 3;console.log(bar); // 1console.log(baz); // 2console.log(qux); // 3}foo(); // Prints each variable successfullyconsole.log(bar); // ReferenceError: bar is not definedconsole.log(baz); // ReferenceError: baz is not definedconsole.log(qux); // ReferenceError: qux is not defined
In the following example, bar is accessible outside of the if block but baz and quz are not.
if (true) {var bar = 1;let baz = 2;const qux = 3;}// var variables are accessible anywhere in the function scope.console.log(bar); // 1// let and const variables are not accessible outside of the block they were defined in.console.log(baz); // ReferenceError: baz is not definedconsole.log(qux); // ReferenceError: qux is not defined
Initialization
var and let variables can be initialized without a value but const declarations must be initialized.
var foo; // Oklet bar; // Okconst baz; // SyntaxError: Missing initializer in const declaration
Redeclaration
Redeclaring a variable with var will not throw an error, but let and const will.
var foo = 1;var foo = 2; // Okconsole.log(foo); // Should print 2, but SyntaxError from baz prevents the code executing.let baz = 3;let baz = 4; // Uncaught SyntaxError: Identifier 'baz' has already been declared
Reassignment
let and const differ in that var and let allow reassigning the variable's value while const does not.
var foo = 1;foo = 2; // This is fine.let bar = 3;bar = 4; // This is fine.const baz = 5;baz = 6; // Uncaught TypeError: Assignment to constant variable.
Accessing before declaration
var ,let and const declared variables are all hoisted. var declared variables are auto-initialized with an undefined value. However, let and const variables are not initialized and accessing them before the declaration will result in a ReferenceError exception because they are in a "temporal dead zone" from the start of the block until the declaration is processed.
console.log(foo); // undefinedvar foo = 'foo';console.log(baz); // ReferenceError: Cannot access 'baz' before initializationlet baz = 'baz';console.log(bar); // ReferenceError: Cannot access 'baz' before initializationconst bar = 'bar';
Notes
- In modern JavaScript, it's generally recommended to use
constby default for variables that don't need to be reassigned. This promotes immutability and prevents accidental changes. - Use
letwhen you need to reassign a variable within its scope. - Avoid using
vardue to its potential for scoping issues and hoisting behavior. - If you need to target older browsers, write your code using
let/const, and use a transpiler like Babel compile your code to older syntax.