21 Jan 2015 Javascript Block Level Scope Management

We will have a look at new feature related to scope management in ES6 (Harmony)

What will be the output for this script? Will it run with out errors?

function example(){
"use strict"
console.log(msg);
var msg="hello world";
}
example();

Yes it will compile but it shows message as undefined.

Generally we expects compile or warning. Why?? But one of drawback of Hoisting which is JavaScript's default behavior of moving declarations to the top.

What will be the output for this script? Will it run with out errors?

function example2() {
    "use strict"
    for (var i = 1; i < 5; i++) {
        setTimeout(function () {
            console.log("Iteration"+i);
        }, 10)
    }
    console.log("Last"+i);
}
example2();

Output is

Last5
Iteration5
Iteration5
Iteration5
Iteration5

Why? 5 it is out of my data range of for loop. This behaviour due to Closure access sample reference of variable i and Hoisting

Can I improve this code as

function example2_1() {
    "use strict"
    for (var i = 1; i < 5; i++) {
        var temp = i;
        setTimeout(
            function () {
                (function (j) {
                    console.log(j);
                })(temp);
            }, 10)
    }
}
example2_1();

Now Output as

Last5
Iteration4
Iteration4
Iteration4
Iteration4

It is completely different output and it shows last value because variable was set with last value while execution of function.

We improve this code with immediately invoked function expression(IIFE) as

function example2_1() {
    "use strict"
    for (var i = 1; i < 5; i++) {
        var tempfn = (function(j){
            return function(){
            console.log("Iteration"+j);
            }
        })(i);
        setTimeout(tempfn, 10)
    }
    console.log("Last"+i);
}
example2_1();

Here IIFE tempfn is new function that new scope with j

There are known scope limitation of javascript ES5.It addressed through new concept of let in ES6

Rewrite both examples replace let instead of var

function example() {
    "use strict"
    try{
    console.log(msg);
    let msg = "hello world";
    }catch(e){
    console.log(e);
    }
}
example();

function example2() {
    "use strict"
    for (let i = 1; i < 5; i++) {
        setTimeout(function () {
            console.log(i);
        }, 10)
    }
}
example2();

Output:

[ReferenceError: msg is not defined]
[ReferenceError: i is not defined]
Iteration1
Iteration2
Iteration3
Iteration4

It gives expected result because the scope of variables maintainanced with the block

Update on 23.01.2015: IIFE section was introduced to solve scope issue with previous ES6 version