Javascript: var, let and const

0
338

Here we will learn to know the different keywords that allow you to declare variables on Javascript: all the differences between var, let and const.

The older generation Javascript developers are used to declare all the variables of their own scripts through the keyword <code>var</code>, since this was the only possibility until the advent of the ECMA6 specification.

This new specification has in fact introduced also the keywords <code>let</code> and <code>const</code>, which act as updates and extensions of the mere concept of <code>var</code>. But what are the real and concrete differences between these identifiers, and why should we use them in our scripts? In this article we will make complete clarity on this important matter.

Consider the following snippet:

var x = 10;
var y = 20;
var z = 30;

In this way 3 variables are declared (x, y and z) to which values ​​are immediately assigned. But there is one more step to know: the variables declared in this way are considered as global variables , or better, belonging to the global scope .

The scope , in fact, is the answer to why other identifiers were created to construct variables, a question that a less experienced developer could, rightly, ask himself.

Global and local scope

In Javascript, a variable declared with the keyword <code>var</code> belongs to the global object window, and is also accessible as follows:

var x = 10;
var p = document.getElementById('demo');
p.innerHTML = window.x;

Use xor window.xis the same thing. A global variable can also be declared and assigned by bypassing the keyword var, becoming also available as an object property window:

y = 20;
var p = document.getElementById('demo');
p.innerHTML = window.y;

This particular object-oriented hierarchy is essential for creating more advanced scripts, such as accessing global variables using strings as identifiers.

Now, we know that as in all programming languages, even in Javascript we can declare and use the functions . In functions, however, there is a local scope, which is different from the global scope. Let’s see the following example:

var x = "out";
function faiQualcosa() {
  var x = "inside";
  console.log(x);
}
faiQualcosa(); // inside
console.log(x); // out

As we can see, we declare via the keyword <code>var</code> the variable x both outside the function, in the window object, and inside the function do Something. In this case Javascript has no problem interpreting the two variables, and in fact the global one is not altered.

Things change if we assign a value x in the function without declaring the variable with the keyword <code>var</code>:

var x = "fuori";
function faiQualcosa() {
  x = "inside";
  console.log(x);
}
faiQualcosa(); // inside
console.log(x); // inside

This happens because in this case we did not specify that the variable x must have a local scope. Since global variables are accessible from within the functions, the value of x is altered. The opposite is not true: the variables declared in the functions, therefore having local scope, are NOT accessible from outside the function.

We can therefore say that the variables declared with var have a local / global scope depending on whether they are declared inside or outside the functions.

Block scope

The ECMA2015 specification introduced the block scope. A “block” is defined by curly braces <code>{</code> and <code>}</code> contains portions of code that are “unto itself” relative to the global code.

The biggest and most obvious difference between <code>var</code> and <code>let</code> is right in the scope. A variable declared with <code>var</code>, it has NO block scope . This means that a variable declared in a block using var is also accessible outside the block:

// global code
// ...
// block
{
    var x = 2;
}
// x is available

So the following code:

var i = 0;
if (true) {
  var i = 1;
}
console.log(i); // 1

Rewrite the value of the variable <code>i</code>, which will also be modified outside the block. This behavior is not always desired, especially in the modern JavaScript programming style, in which the block scope can create inconsistencies.

For this reason the identifier was created <code>let</code>, which unlike the previous one, HA block scope. So, a snippet identical to the previous one, but using let, produces the following result:

let i = 0;
if (true) {
  let i = 1;
}
console.log(i); // 0

Although the variable i is reassigned within the block if, it is not a problem using the let operator, because that assignment is local and referred to the block of membership code, while the external one refers to the block of global code.

The general rule, using let, is described by the following snippet:

{
    let x = 2;
}
// x It is not accessible

var VS let

We see the differences between the use of <code>var</code> and <code>let</code>, enclosed in this analysis.

Block scope

var x = 10;
// who x è 10
{
    var x = 2;
    // who x è 2
}
// who x è 2
var x = 10;
// who x è 10
{
    let x = 2;
    // who x è 2
}
// who x è 10

The difference is abysmal. In the first case, not having a block scope, the variable x is overwritten. In the second case, the global variable x is not affected by the declaration of the local x variable for the block of code in which it is defined through <code>let</code>.

With a bit of practice and good craftsmanship in writing modern JavaScript, using it <code>let</code> in conjunction with <code>var</code> will become increasingly intuitive and simple.

Loop scope

The same functionality just seen is also active in the scope of loops, such as <code>for</code>:

var i = 5;
for (var i = 0; i &amp;amp;lt; 10; i++) {
    // operations
}
// Qui i è 10

If instead we use let:

let i = 5;
for (let i = 0; i &amp;amp;lt; 10; i++) {
    // operations
}
// Qui i è 5

In the first case, using var, the loop alters the value of the global variable i. In the second case, using let, we have the loop scope, so the global variable is not touched.

Function scope

var and let both have a local scope for declaration in functions:

function myFunction() {
    var myName = "John";   // Function Scope
}
function&amp;amp;nbsp;myOtherFunction() {
 &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;let&amp;amp;nbsp;myName =&amp;amp;nbsp;"John";&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;// Function Scope
}

Global scope

Same with regards to the global scope:

var x = 2;       // Global scope
let&amp;amp;nbsp;y =&amp;amp;nbsp;2;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;// Global scope

However, here there is a difference to be aware of. As we said earlier, the global variables declared with var are accessible via the global window object. However, the same can not be said for variables declared with let, which are NOT accessible via the window object:

var myName = "John";
var p = document.getElementById('demo');
p.innerHTML = window.myName;	// okay
let myName = "John";
var p = document.getElementById('demo');
p.innerHTML = window.myName;	// error

re declaration

Redefine a var variable using the var identifier is allowed (everywhere):

var x = 2;
// ora x è 2
var x = 3;
// ora x è 3

Redefine a let variable using the let identifier in a different scope (such as blocking) is allowed:

let x = 2;       // allowed
{
    let x = 3;   // allowed
}
{
    let x = 4;   // allowed
}

Redefining a var variable using the let identifier , in the global scope or in a block scope is NOT allowed:

var x = 2;       // allowed
let x = 3;       // Non allowed
{
    var x = 4;   // allowed
    let x = 5   // Non allowed
}

Redefining a let variable using the let identifier , in the global scope or in a block scope is NOT allowed:

let x = 2;       // allowed
let x = 3;       // Non allowed
{
    let x = 4;   // allowed
    let x = 5;   // Non allowed
}

To redefine a let variable using the var identifier , in the global scope or in a block scope, is NOT allowed:

let x = 2;       // allowed
var x = 3;       // Non allowed
{
    let x = 4;   // allowed
    var x = 5;   // Non allowed
}

Hoisting

The term hoisting identifies the computation of Javascript in which the variables could be used BEFORE their declaration, since the declarations of the variables, even if placed for example at the end of the script, were “pushed” above, and therefore the procedure was perfectly legal. With the introduction of the indentifier, however, this is no longer true.

With <code>var</code> the keyoword, hoisting is perfectly legal:

// here you can use the variable myName even if its declaration
// is carried out later
myName = "John";
var p = document.getElementById('demo');
p.innerHTML = myName;	// okay
// declaration
var myName;

With the keyword <code>let</code>, the hoisting is not legal and will result in a <code>ReferenceError</code>, since unlike the var variables that are initialized as <code>undefined</code>, the variables let are not initialized:

// here you CAN NOT use the myName variable if your declaration
// is carried out later
var p = document.getElementById('demo');
p.innerHTML = myName;	// Reference Error
// declaration
let myName;

const

Now let’s see the third and last identifier (the second novelty of ECMA 6 in terms of variable identifiers) that can be used for the declaration of variables.

The variables declared with const behave similarly to those declared with let, with the difference that the former can not be reassigned . This completely eliminates the possibility of overwriting the const variables. For example:

const PI = 3.141592653589793;
PI = 3.14;      // error
PI = PI + 10;   // error

Also the const variables are affected by the block scope, indentically to the let. The following snippet is perfectly legal:

var x = 10;
// who x è 10
{
    const x = 2;
    // who x è 2
}
// who x è 10

Another peculiarity of the variables <code>const</code> lies in the fact that they must necessarily be assigned in the declaration phase. The following line of code is valid:

const PI = 3.14159265359;

While the following will produce a type error <code>SyntaxError</code>:

const PI;
PI = 3.14159265359;
// Uncaught SyntaxError: Missing initializer in const declaration

In this case the const variables may appear to be true constants , since they can not even be declared and assigned later (as a variable):

const i;
// Uncaught SyntaxError: Missing initializer in const declaration

However, this feature has a slight exception, which concerns, in the case of non-primitive data types (ie arrays and objects) the values, properties and methods of the variables. If it is not possible to reassign the data type in a const variable, however, it is possible to reassign one of its elements:

// creating an object
const car = {type:"Fiat", model:"500", color:"white"};
// legal: update properties
car.color = "red";
// legal: update properties
car.owner = "Johnson";

However, it is not possible to update the const variable by reassignment:

const car = {type:"Fiat", model:"500", color:"white"};
car = {type:"Volvo", model:"EX60", color:"red"};    // ERROR

This snippet generates a SyntaxError: <code>Uncaught SyntaxError: Identifier ‘car’ has already been declared</code>.

The exact same thing happens with arrays. You can change the values ​​of a const array variable, but do not reassign it:

const cars = ["Saab", "Volvo", "BMW"];
// legal: property update
cars[0] = "Toyota";
// legal: adding an item
cars.push("Audi");
// illegal
cars = ["Toyota",&amp;amp;nbsp;"Volvo",&amp;amp;nbsp;"Audi"];&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;// ERROR

Conclusion

As we have seen, we have two new and powerful tools at our disposal, which allow us to write Javascript code in a more intuitive, clear and concise way. Unlike some developers who claim that let and const have to completely replace var, my opinion is that all three identifiers must be used in the correct situations, knowing perfectly their behaviors and their characteristics. The var identifier remains very important also for reasons of backward compatibility.

LEAVE A REPLY

Please enter your comment!
Please enter your name here