Defined variable in outer scope is not defined in

2019-03-04 11:57发布

问题:

This question already has an answer here:

  • Are variables declared with let or const not hoisted in ES6? 3 answers

The following code throws a ReferenceError 'a is not defined'.

{
    let a = 'a1';
    {
        console.log(a);
        let a = 'a2';
    }
}

As do the next one.

{
    const a = 'a1';
    {
        console.log(a);
        const a = 'a2';
    }
}

If you instead use var declarations it works as I expect it to. (No error error thrown and 'a1' logged.)

It gets even harder for me to comprehend when I try to analyze the following code.

{
    let a = 'a1';
    {
        console.log(a);
        var a = 'a2';
    }
}

It throws a SyntaxError, "Identifier 'a' has already been declared".

Naïvely I expected an identifier to be shadowed not until after a let or const declaration, like the behavior of let in Clojure or let* in Racket. As described clearly on MDN, this is not how it works.

But why does it work this way? Why does Racket have both a let and a let* form?

回答1:

This is caused by hoisting the internal let or const to the top of the block (MDN), and create a Temporal Dead Zone.

In ECMAScript 2015, let will hoist the variable to the top of the block. However, referencing the variable in the block before the variable declaration results in a ReferenceError. The variable is in a "temporal dead zone" from the start of the block until the declaration is processed.

The reason behind this is simple - silent failing vs throwing error.

In this example, a similar setting is giving the result as undefined because of the var hoisting. This is a silent error, and it might be very hard to debug.

{
    var a = 'a1';
    (function() {
        console.log(a);
        var a = 'a2';
    })();
}

If you'll use let or const an error will be thrown:

{
  let a = 'a1';
  (function() {
    console.log(a);
    let a = 'a2';
  })();
}

You can find more info about the temporal dead zone in the article TEMPORAL DEAD ZONE (TDZ) DEMYSTIFIED.