avatarMaya Shavin

Summary

The provided web content offers an in-depth comparison of the var, let, and const variable declaration keywords in ES6 (ECMAScript 2015), highlighting the benefits and use-cases of the newer let and const over the classical var.

Abstract

The article "ES6 cool stuffs — var, let and const in depth" delves into the nuances of variable declarations in JavaScript, focusing on the enhancements brought by ES6 with the introduction of let and const. It explains the concept of hoisting and its implications on variable scope, particularly with var. The author illustrates how let and const provide block-level scoping, which helps prevent common bugs associated with the function-level scoping of var. The article also discusses the immutability of const, which ensures that variables declared with it cannot be reassigned, although objects declared with const can still be mutable. The advantages of using let and const are emphasized, including avoiding global namespace pollution, reducing hidden bugs, and writing more predictable and maintainable code. The conclusion suggests that while let and const offer significant improvements, they are not replacements for var but rather additional tools for developers to write cleaner, safer code.

Opinions

  • The author suggests that the flexibility of var can lead to potential issues and should be used carefully.
  • Let and const are praised for providing more restrictive scoping, which can lead to fewer bugs and clearer code intent.
  • The article conveys that let and const are not meant to replace var entirely but to offer more control and safety in variable declarations.
  • The author expresses that the use of let and const can improve code readability and reliability, making it easier for developers to understand and maintain the codebase.
  • There is an implied preference for let and const over var for modern JavaScript development, with the recommendation to choose the appropriate declaration based on specific needs.

ES6 cool stuffs —var, let and const in depth

A way to explain using Groot. Character credit goes to Marvel 😄

In this article, we will continue exploring some of ES6 cool stuffs — let, const statement against our classical var statement. It won’t be long, I promise.

Let’s begin!

JavaScript variables are containers for storing data values

How do you normally create new variable in Javascript? OK, i know it’s a silly question since it’s too basic to ask — we all use the “var” statement.

Var

var firstVar; //declare firstVar width default value - undefined
var secondVar = 2; //declare and assign 2 to secondVar variable.

Just in case someone is wondering, var stands for “variable” in English (obviously 😆).

Like many modern languages, JavaScript provides us such flexibility that there is no need to decide on a specific type for our variable when we declare them.

Integer? String? Object? Function? … —one var fits all.

Life is easy, until you encounter something like this:

var increment = 1;
if (increment === 1){
   var increment; //re-declare increment with default value
   //Do something
}
console.log(increment); //What will be printed here?

What is going on here? First of all, we will need to mention about hoisting.

A closer look — Hoisting

Hoisting, refers to the default behavior of Javascript to process and put all variables and functions declarations into memory first during compile phase of its execution context, regardless where they are written in code.

In more common explanation, it is the JS’s behavior of moving all the declarations to the top of current scope — not physically, aka no change to your code at all — and will be processed before everything else.

Take the example above, during the compile phase the code will be understood as

var increment;
var increment;
increment = 1;
if (increment === 1){
    ...
}
console.log(increment); //print 1

Or in another example:

var x = 0;
y = 1;
console.log(sumOf(x,y));
var y;
function sumOf(a, b){ return a + b; }

It will be processed as:

var x;
var y;
function sumOf(a, b){ return a + b; }
x = 0;
y = 1;
console.log(sumOf(x,y));

Note here JavaScript hoisting only applies to declarations, not assignments. All value assignments will be processed at the same location where they are written/located in the code, resulting in:

console.log(x); 
x = 3; 
var x = 1; 
console.log(x);

will print out undefined, 1 and NOT 1, 3 as some may thought.

In addition, we mentioned above about execution context, which is — according to JavaScript documentation the scope of a declared var variable. So what about it and how does it affect var variable declaration & assignment?

What is execution context?

Execution context is the environment where Javascript code is executed/evaluated. It can be either:

  • Global — default environment
  • Functional — environment inside a function.
  • Eval — environment inside eval function.

Hence here the scope of a var variable is either within enclosing function or global context.

Any other block context — means block of code inside {} curly braces , code statement, expression, etc…—which is not from 3 defined types above will not affect the mentioned variable’s scope.

As a result, declaring a variable in a block of code statement, expression— if…else … statement, for loop, etc — will be understood as declaring it at the top in the compiler/creation phase.

function testMe(){
   while(true){
      var x = 2;
      break;
   }
   console.log(x); 
   //Still print 2 even though x is declared inside while loop
}

And so, that’s var. As we can see, this statement provides all the flexibility needed for developers (But please, don’t overuse it!). So why do ES6 bother to introduce 2 more statements — let and const ? Let’s find out.

Let

let, similar to var, declares a variable and allows (optionally) to assign any value to it. However, unlike var, it declares variable only as block scope local one.

It means the variable will be declared, existed and limited to use only inside block ({}), statement or expression and also available to its sub-block beside normal execution context (enclosing function, etc).

Therefore, in the above example, while x is not limited within while block scope like most language will do, if we replace var by let, the result will change:

function testMe(){
   while(true){
      let x = 2;
      break;
   }
   console.log(x); //ReferenceError: x is not defined
}

Yup, not undefined, not null, not 2 but a ReferenceError instead.

This ensures the locality of the variable, and we can rest assured that we won’t change by mistake any variable with same name declared somewhere before. Like in this situation:

var x = 1;
{
   let x = 3;
}
console.log(x); //Still 1

Yippie, less chance for 🐛 to go un-noticeable!

But wait, there is more. Since it is limited by block scope, we finally can implement private members without the help of closure.

var Person;
{
   let name;
   Person = function(_name){ 
       name = _name;
   };
   Person.prototype.getName = () => name;
}
var person = new Person('Maya');
console.log(name); //Nothing is printed
console.log(person.getName()); //Maya

Another important difference from var is that variable hoisting doesn’t apply to let, which means during compile phase, let declaration will stay where it is and will not be processed first among other code — aka will not move to the top of context like var. Thus in executing this example,

x = 5;
y = 2;
let y; 
var x;

it will yield ReferenceError again for y, but not for x.

Finally, let doesn’t create a property on global object, unlike var when being used in the global context. So no messing around with global object by accident!!! 🚀

var x = 5;
let y = 4;
console.log(this.x); //5
console.log(window.x); //5
console.log(this.y); //undefined
console.log(window.y); //undefined

And unlike var, re-declaring a let variable will throw SyntaxError.

SyntaxError for x

So one thing for certain, when using letwe will have more restrictions/limitations (for the better I must say) than the normal way of var declaration. What about const?

Const

Let’s say, you have some data variables like templates, default messages, etc… They are meant to be used as constants — without changing. How will you make sure these data will stay unchanged throughout application using JavaScript?

Before ES6, one way — be careful what you write (or pray that other developer also notice and understand the naming conversion you use for constant variables).

After ES6 (thank God) we have const

const — same as let allows to declare and initialize a local block-scoped variable. Thus, it has all the restrictions of let such as:

  • Declared variables are only available to use in inside block {} of code, statement, expressions beside the normal execution context.
  • No variable hoisting applies to const
  • No property created in global object when it is used in global context.
  • Declared variable can’t be re-declared.

In addition, as you can guess, const — stands for constants:

  • Declared variable has to be initialized with a value.
const myConstants; //SyntaxError: Missing initializer in const declaration
  • Declared variable can ONLY be assigned with a value ONCE. No re-assignment — as expected for a constant value.

But one downside is that if the assigned value itself is in a form of an object (object, array, etc), it still can be modified. For example:

const myConstant = {name: "Constant"};
myConstant = {name: "new Constant"}; //Error
myConstant.name = "new Constant"; //OK
console.log(myConstant.name); //new Constant
const arr = [1, 2];
arr = [2,3]; //Error
arr[0] = 2; //OK
console.log(arr); //[2,2]

Clear and easy to understand, isn’t it?

In general, you probably notice the benefits these new statements bring to us by now, hence let’s sum it up.

Advantages of let and const

  • Avoid polluting our global object with unnecessary properties.
  • Avoid hidden 🐛 — such as modifying a constant value by mistake, updating wrong variables which are in different scope block but declared with same name, etc…
  • Avoid unnecessary hoisting.
  • Add more restrictions to force our code more reliable, organized and easier to read (how am I supposed to know if a variable is supposed to be const if it is declared as var ??).

Conclusion

Actually no matter how much advantages let and const can have against var, they are not meant to replace var but more as additional ways to provide more constraint functionalities to JavaScript and help developers saving time in code reviewing and reading.

My piece of advice, as always, is to analyze your need first and only then choose the statement accordingly, even if it’s just a small variable — remember, a lot of small and seem-to-be unimportant things can lead to a big scary nightmare someday if they are not handled with care in the beginning😉.

After all, who doesn’t like writing clean and safe code? 😃

More on ES6:

More on Data Structures:

If you like this post, don’t forget to give me a 👏 below ⏬️ . It will surely motivate me a lot 😊

If you love to read more, feel free to check out my articles.

If you’d like to catch up with me sometimes, follow me on Twitter | Facebook or simply visit my portfolio website.

JavaScript
Programming
ES6
Front End Development
Coding
Recommended from ReadMedium