Scoping rules
The main difference is scoping rules. Variables declared by var keyword are scoped to the immediate function body (hence the function scope) while let variables are scoped to the immediate enclosing block denoted by { } (hence the block scope).
function run() {
var foo = "Foo";
let bar = "Bar";
console.log(foo, bar); // Foo Bar
{
var moo = "Mooo"
let baz = "Bazz";
console.log(moo, baz); // Mooo Bazz
}
console.log(moo); // Mooo
console.log(baz); // ReferenceError
}
run();
The reason why let keyword was introduced to the language was function scope is confusing and was one of the main sources of bugs in JavaScript.
Take a look at this example from another Stack Overflow question:
var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
// and store them in funcs
funcs[i] = function() {
// each should log its value.
console.log("My value: " + i);
};
}
for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}
My value: 3 was output to console each time funcs[j](); was invoked since anonymous functions were bound to the same variable.
People had to create immediately invoked functions to capture correct values from the loops but that was also hairy.
Hoisting
Variables declared with var keyword are hoisted and initialized which means they are accessible in their enclosing scope even before they are declared, however their value is undefined before the declaration statement is reached:
function checkHoisting() {
console.log(foo); // undefined
var foo = "Foo";
console.log(foo); // Foo
}
checkHoisting();
let variables are hoisted but not initialized until their definition is evaluated. Accessing them before the initialization results in a ReferenceError. The variable is said to be in the temporal dead zone from the start of the block until the declaration statement is processed.
function checkHoisting() {
console.log(foo); // ReferenceError
let foo = "Foo";
console.log(foo); // Foo
}
checkHoisting();
Creating global object property
At the top level, let, unlike var, does not create a property on the global object:
var foo = "Foo"; // globally scoped
let bar = "Bar"; // globally scoped but not part of the global object
console.log(window.foo); // Foo
console.log(window.bar); // undefined
Redeclaration
In strict mode, var will let you re-declare the same variable in the same scope while let raises a SyntaxError.
'use strict';
var foo = "foo1";
var foo = "foo2"; // No problem, 'foo1' is replaced with 'foo2'.
let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared
Scoping rules
The main difference is scoping rules. Variables declared by var keyword are scoped to the immediate function body (hence the function scope) while let variables are scoped to the immediate enclosing block denoted by { } (hence the block scope).
function run() {
var foo = "Foo";
let bar = "Bar";
console.log(foo, bar); // Foo Bar
{
var moo = "Mooo"
let baz = "Bazz";
console.log(moo, baz); // Mooo Bazz
}
console.log(moo); // Mooo
console.log(baz); // ReferenceError
}
run();
The reason why let keyword was introduced to the language was function scope is confusing and was one of the main sources of bugs in JavaScript.
Take a look at this example from another Stack Overflow question:
var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
// and store them in funcs
funcs[i] = function() {
// each should log its value.
console.log("My value: " + i);
};
}
for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}
My value: 3 was output to console each time funcs[j](); was invoked since anonymous functions were bound to the same variable.
People had to create immediately invoked functions to capture correct values from the loops but that was also hairy.
Hoisting
Variables declared with var keyword are hoisted and initialized which means they are accessible in their enclosing scope even before they are declared, however their value is undefined before the declaration statement is reached:
function checkHoisting() {
console.log(foo); // undefined
var foo = "Foo";
console.log(foo); // Foo
}
checkHoisting();
let variables are hoisted but not initialized until their definition is evaluated. Accessing them before the initialization results in a ReferenceError. The variable is said to be in the temporal dead zone from the start of the block until the declaration statement is processed.
function checkHoisting() {
console.log(foo); // ReferenceError
let foo = "Foo";
console.log(foo); // Foo
}
checkHoisting();
Creating global object property
At the top level, let, unlike var, does not create a property on the global object:
var foo = "Foo"; // globally scoped
let bar = "Bar"; // globally scoped but not part of the global object
console.log(window.foo); // Foo
console.log(window.bar); // undefined
Redeclaration
In strict mode, var will let you re-declare the same variable in the same scope while let raises a SyntaxError.
'use strict';
var foo = "foo1";
var foo = "foo2"; // No problem, 'foo1' is replaced with 'foo2'.
let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared
let can also be used to avoid problems with closures. It binds fresh value rather than keeping an old reference as shown in examples below.
for(var i=1; i<6; i++) {
$("#div" + i).click(function () { console.log(i); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Clicking on each number will log to console:</p>
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>
Code above demonstrates a classic JavaScript closure problem. Reference to the i variable is being stored in the click handler closure, rather than the actual value of i.
Every single click handler will refer to the same object because there’s only one counter object which holds 6 so you get six on each click.
A general workaround is to wrap this in an anonymous function and pass i as an argument. Such issues can also be avoided now by using let instead var as shown in the code below.
(Tested in Chrome and Firefox 50)
for(let i=1; i<6; i++) {
$("#div" + i).click(function () { console.log(i); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Clicking on each number will log to console:</p>
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>
Hi everyone!
I'm pretty new to web development and have started to read a little bit about javascript. Right now I'm trying to learn how to declare a function but realized that there is different ways to do this using var, let or const. Since I'm new to this, most of the explanation on the internet is pretty advanced to understand atm, so could anyone explain the differences for me very short short and easy, alternatively give me a link that explain it in pretty easy terms?
Thanks in advance!
(Edit: Thank you so much for the answers, rly appreciate it!)
Videos
I am completely new to JavaScript. Just started exploring different aspects of ES6. What I noticed is, most of my seniors who has worked and implemented JavaScript in many of their projects, almost all of them suggested to use the keyword "let" instead of "var" while working with a variable declaration. Can anyone give me some insight for the preference of let over var? Thanks in advance.
for (var i = 0; i < 10; i++) {
} or
for (let i = 0; i < 10; i++) {
}