ES6 - let there be block scope

Of course everybody programming in JavaScript knows the key word var, because it is used to declare variables. But var comes with subtle "problems" not everybody knows about. let was introduced in ES6 to fix this.

The problem with var is the unusual scoping of variables declared with this key word. Unusual because many programming languages like Java, C++ and C# have different scoping. The scope of a variable is the part of the souce code in which this variable is valid and can be referred to.

 

In JavaScript, omitting the key word var (or let) by just assigning a value to a variable that is not declared, tells the interpreter/compiler to assume the global scope for this variable. This is certainly a very dangerous "feature" and a design flaw of the language. This was "fixed" by introducing strict mode in ES5, which throws an error in this case, so in strict mode you have to use var (or let). 

 

So by using var to declare a variable inside a function, the variable is valid and can be referred to everywhere inside this function. That means even if you declare it in the very last line of the function, you can refer to it in the very first line of the function:

function fun () {
  console.log(x);
  ...
  var x = 1;
}

Of course x is not getting its value assigned before the very last line, so the output is undefined in this case. But omitting the declaration altogether will result in an error (x is not defined). So the above example can also be written as:

function fun () {
  var x;
  console.log(x);
  ...
  x = 1;
}

Here the declaration of x and the first assignment (definition) are separate, the declaration is put at the beginning of the function. This is what the interpreter/compiler makes from the first example. This is also true if the declaration is inside a block:

function fun () {
  console.log(x);
  if (!x) {
    var x = 1;
  }
  console.log(x);
}

There is no error in this case because the variable x is valid throughout the function, although it is declared inside the if block. The first console output yields undefined (because x is only declared at this point and not defined) and the second yields "1", because x is defined as 1 inside the if block.

 

The reason why this is problematic is, that it is not what one would expect, especially coming from a different programming language. If code doesn't behave like expected. there is a high probability that errors are introduced which are hard to find. So for ES6 there is a fix for it: let.

function fun () {
   if (true) {
    let x = 1;
  }

  console.log(x);
}

This will throw an error in the last line of the function, because x is not valid there. This is expected behavior, since x is declared in the if block and is not valid outside of that block. What about this:

function fun () {
  var x;
  console.log(x);
  if (!x) {
    let x = 1;
    x++;
  }
  console.log(x);
}

This is valid (ES6) code (no error) and yields undefined twice. Actually there are two variables declared in this example and both are called x. This is possible because there are two scopes, the first being the function scope, in which the first x is declared, the second the if block scope, where the second x is declared. The declaration of the second x shadows (hides) the declaration of the first x, so the first x is not changed inside the if block. 

 

Another difference: variables declared with let are not valid before the let statement. So this code throws an error:

function fun () {
  console.log(x);
  let x = 1;    
  console.log(x);
}

 

The so called hoisting of the variable declaration to the top of the scope (this is what var does) is not happening with let.

 

let: the better var?

So is let the better var? Short answer: yes, because it fixes the problematic parts of var. Long answer: yes, but to use it, you should check if the following is true for your use case:

So actually there is very little reason to stick to var and by using let you are making your code more robust and easier to understand and to debug.

 

Kommentar schreiben

Kommentare: 1
  • #1

    cyber (Mittwoch, 06 Januar 2016 15:49)

    Good article...thank