DEV Community

Cover image for [freeCodeCamp] ES6 - var, let and const
Prashant Sharma
Prashant Sharma

Posted on • Originally published at gutsytechster.wordpress.com

[freeCodeCamp] ES6 - var, let and const

Hi there folks! Continuing the JavaScript learning from freeCodeCamp, this time we move ahead from the Basic JavaScript and would start with the ES6. ECMAScript 6 or ES6 is the major JS version which introduced a variety of helpful features, released in 2015. Going with this, we will explore those features and how to use them in upcoming posts as well.

This post mainly covers the caveats regarding the variable declaration and how ES6 changes its behaviour. So, let's start without delaying anything.

Difference between var and let keywords

The usage of var had some issues, which we'll come across little by little. However, one potential issue is that variables declared with var can be overridden without any errors. For e.g.

var myName = Prashant;
var myName = Akash; 
console.log(myName);  // Akash

As you may see, we've overridden the variable myName, but JavaScript didn't raise any error. With application with larger source code, we may accidentally overwrite a variable, which we don't intend do. This could lead to unexpected behaviours and difficulties in debugging.

To resolve this, ES6 provides the keyword let for variable declaration. If we were to use let instead of var in the above example, the second initialization would lead to an error.

We can also use the "use_strict" to enable the strict mode. This would catch common mistakes and unsafe actions.
For e.g.

"use strict";
x = 3.14; // throws an error because x is not declared

Scope differences between var and let keywords

If we go back and try to remember the behaviour of the var keyword w.r.t scopes, we know that any variable declared with it is global and if declared within a function, it's scope is limited to that function only.

let behaves in a similar way, but with some extra features. For e.g. when we declare a loop variable using the var keyword, that becomes global. However, declaring the same, using let would result in its scope limited to the block of the loop.

Let's see an example

arr = [1, 2, 3, 4];
for (var i = 0; i < arr.length; i++) {
   arr[i]++;
}
console.log(i);  // returns 4

You may notice that the variable i is accessible outside the loop. If you were to use it again elsewhere, it'd be using the updated value, which might result in unexpected behaviour. However, with let, this doesn't happen i.e. the loop variable i will only be accessible within the loop block and not outside of it.

Let's see another example

function checkScope() {
  'use strict';
  let i = 'function scope';
  if (true) {
    let i = 'block scope';
    console.log('Block scope i is: ', i);
  }
  console.log('Function scope i is: ', i);
  return i;
}

Before we discuss the output of the above code, a doubt may arise to you. You may ask, that let should not allow the re-declaration of the variable i at all. The catch here is that it restricts the same declaration within the same scope. In the above piece of code, the second initialization is within a local scope. Hence let does not raise any error. 

Yes, if you would've tried to initialize it outside of the if block, it should have a complaint about that. Now, let's move to the output of the above code.

The output of this function would be

Block scope i is:  block scope
Function scope i is:  function scope

And can you guess which value of i would be returned? Think!

The answer is function scope would be returned, as the variable i within the local scope of if condition is not visible outside of its block. Hence the global i is returned.

What if I change the code slightly to this

function checkScope() {
  'use strict';
  let i = 'function scope';
  if (true) {
    i = 'block scope';
    console.log('Block scope i is: ', i);
  }
  console.log('Function scope i is: ', i);
  return i;
}

What do you think, would be returned now? Before that, did you notice the change? I removed the let keyword from inside of if block. That's it. Now, think!

This time, block scope would be returned. I see you ask why? Well, it's because this time instead of declaring a new variable with the same name in scope, we are instead, overriding the global variable i. Hence, the changes to it are reflected outside of the function.

Variable declaration using the const keyword

ES6 not only provides the let keyword to declare a variable but also a const keyword to do so. The difference is that the variables declared with const are read-only. It means that once the variable is declared, it cannot be reassigned. These variable act as a constant value.

It is a common practice to declare constants using the uppercase letters with words separated with underscores.

The use of const helps us to avoid accidentally changing the constants within a program. An example of its use can be seen as

const PI = 3.14;
PI = 2.17; // throws an error

Mutating arrays declared with const

We should know that objects, arrays or functions would be mutable when assigned to a variable using const. It is actually the variable identifier, which cannot be reassigned.

Let's see an example for an array

const s = [4, 5, 6, 7];
s = [1, 2, 3]; // throws an error, as assignment to a const variable
s[4] = 8; // this would work fine
console.log(s);  // [4, 5, 6, 8]

The thing which is to be noticed here is that the values within the array are mutable. Even though we change the array elements, the variable s would still point to the same memory location. Only the value to that memory location has been changed.

Yes, if we would try to point s to some other memory location i.e. some other array or value, it would throw an error.

Preventing object mutation

From the above, we found that const declaration doesn't actually protect the data from mutation. It only prevents the variable identifier to point to some other location instead.

However, if we want to prevent data mutation within an object, JavaScript provides the function Object.freeze.

After the object is frozen, any attempt to add, update or delete the properties would be rejected without any error.

function freezeObj() {
  let MATH_CONSTANTS = {
    PI: 3.14
  };

  Object.freeze(MATH_CONSTANTS);

  MATH_CONSTANTS.PI = 99;  // ignored and mutation won't be allowed
  return MATH_CONSTANTS.PI;
}

The above would still return 3.14. However, if you'd use the strict mode, it will throw an error.

Conclusion

At the end of this post, we found the major differences between var, let and const keywords and where and why of using them. Further, we found that we can also prevent any data mutation using Object.freeze() method which comes in handy at times.

References

We'll meet next time with other ES6 features so that we can improve our JS knowledge further. Till then be curious and keep learning. :)

Top comments (0)