【问题标题】:const already declared in ES6 switch block [duplicate]const 已在 ES6 开关块中声明 [重复]
【发布时间】:2016-01-28 14:58:16
【问题描述】:

考虑文件sample.es6

switch (1) {
    case 1:
        const foo = 1;
        break;
    case 2:
        const foo = 2;
        break;
}

如果我用 Node 运行它,我得到了

$ node --version
v4.2.11
$ node sample.es6 
/tmp/sample.es6:6
const foo = 2;
^

SyntaxError: Identifier 'foo' has already been declared
    at Object.<anonymous> (/tmp/sample.es6:1:11)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Function.Module.runMain (module.js:467:10)
    at startup (node.js:134:18)
    at node.js:961:3

为什么我会收到此错误?节点不应评估 const foo = 2;

【问题讨论】:

  • 你到底想做什么?你想在哪里使用foo
  • 您是否对const 感到困惑,或者为什么当它们位于不同的case 部分时会引发错误?
  • 这是我可以提供的最小示例。我会将foo 传递给函数。为什么当它们位于不同的案例部分时会引发错误。
  • @RaniereSilva:case 部分没有自己的范围,因此其中的多个 foo 声明将相互冲突。您可以将它们包装成块 ({ … }) 来解决这个问题。

标签: javascript node.js constants ecmascript-6


【解决方案1】:

您可以围绕您的案例创建范围块,编译器会很高兴:

switch (1) {
    case 1: {
        // notice these extra curly braces
        const foo = 1;
        break;
    }
    case 2: {
        const foo = 2;
        break;
    }
}

如果您需要更多上下文,请阅读answer from Igor

【讨论】:

  • 这是克服单范围 switch 语句的好技巧!谢谢!
  • 其中一个隐藏的宝石!
  • 这为我节省了一天的时间 +1。
  • javascript,对吧? ?
  • 我从来没有想过 Switch case 默认没有自己的块作用域。很好的答案。
【解决方案2】:

你得到一个SyntaxError,因为你在同一范围内重新声明了一个变量; switch 声明 contains only one underlying block,而不是每个 case 一个块。

JavaScript 在编译时 抛出错误。 “Node不应该评估const foo = 2;”是无关紧要的,因为这个错误发生在Node评估任何东西之前。

const(以及许多新的 ES6 特性,例如新的模块规范)的一个目的是使编译器能够进行一些静态分析。 const 告诉编译器该变量永远不会被重新分配,这使得引擎可以更有效地处理它。

当然,这需要编译时检查以确保变量确实从未重新分配(或重新声明),这就是您看到错误的原因。

【讨论】:

  • 这是const 的一点。另一个是防止我破坏自己的变量。
  • 也许值得一提的是switch语句中只有一个底层块。有人可能会猜测每个案例都有一个块作用域,但事实并非如此。 developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
  • @Christiaan,谢谢,我已经添加了这个澄清(尽管比你指出的要晚得多)。
【解决方案3】:

您可以使用立即调用函数表达式 (IIFE) 进行 const 赋值:

const foo=(function(){
  switch (1) {
    case 1:
      return 1;
      break;
    case 2:
      return 2;
      break;
  }
})();

console.log('foo = '+foo); /* foo = 1 */

或者,您可以使用花括号在案例内部创建一个范围,但您不能访问开关块外部的 foo:

switch (1) {
  case 1: {
    const foo = 1;
    console.log(foo+' from inside'); /* 1 from inside */
  } break;
  case 2: {
    const foo = 2;
    console.log(foo+' from inside');
  } break;
}

console.log(foo+' from outside'); /* foo is not defined */

【讨论】:

  • 替代 IIFE,只需转换为函数并显式调用它。
  • 我真的很喜欢作用域方法。看起来不错。
【解决方案4】:

如果您希望在 case 语句中创建范围,则应使用 (IIFE) 立即调用函数表达式。它将允许您在 case 语句中创建所需的额外范围。

function (value) {
   switch (value) {
     case 1:
       return (function() {
         const foo = 1
         return foo
       }())
       break;
     case 2:
       return (function() {
         const foo = 2
         return foo
       }())
       break;
   }
}

这是一个例子https://jsfiddle.net/hermanleus/e4ceq7xt/2/

希望对你有帮助

【讨论】:

    【解决方案5】:

    使用临时变量确定值,确定值后设置常量。

    let bar;
    switch (1) {
        case 1:
            bar = 1;
            break;
        case 2:
            bar = 2;
            break;
    }
    const foo = bar;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-14
      • 2018-07-08
      • 1970-01-01
      • 2019-06-08
      • 1970-01-01
      • 2021-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多