外部范围中的已定义变量未在内部范围中定义 [英] Defined variable in outer scope is not defined in inner scope

查看:96
本文介绍了外部范围中的已定义变量未在内部范围中定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码引发ReferenceError'a not defined'.

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

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

下一个也是.

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

如果您改为使用var声明,则它将按我的预期工作. (没有引发任何错误并且记录了"a1".)

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';
    }
}

它抛出一个SyntaxError,标识符'a'已经被声明".

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

天真的,我希望标识符不被遮盖,直到let或const声明之后,就像Clojure中let的行为或Racket中let *的行为一样.正如在MDN上明确描述的,这是不是它的工作原理.

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.

但是为什么这样工作?为什么Racket同时具有let和let *形式?

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

推荐答案

这是由于将内部letconst提升到块的顶部引起的(

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

在ECMAScript 2015中,让该变量将其提升到 堵塞.但是,在 变量声明导致ReferenceError.变量位于 从块的开始到声明的时间死区" 已处理.

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.

在此示例中,由于提升了var,因此类似的设置将结果设置为undefined.这是一个无提示的错误,可能很难调试.

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';
    })();
}

如果您使用letconst,将引发错误:

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

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

您可以在文章 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆