为什么const在if()或try {} catch(e){}内的多次运行时会抛出错误?

时间:2010-11-11 19:25:00

标签: javascript firebug constants const

我正在尝试使用const声明一堆常量。我的问题是在Firebug控制台中测试代码会引发错误,抱怨'重新声明const foo'。

我试图将它包装在try{}catch(e){}块中,但这没有帮助,甚至在尝试使用以下代码绕过它时(发布减去所有console.info()“调试”调用为了清楚起见)它仍然会在第二次运行时抛出错误:

if(!chk_constsDeclaredYet) {
  var chk_constsDeclaredYet = true;
  const foo="bar";
}

我的问题是,当const在if(){}中时,当代码第二次“运行”时,为什么const foo甚至被查看?

注意:代码将在firebug javascript控制台中运行,我想要实现的工作流程是:

  1. 将代码粘贴到firebug控制台
  2. 点击运行(创建常量)
  3. 我在控制台中编辑代码而不重新加载页面(常量仍在页面上下文中定义)
  4. 再次点击运行(使用if(){}以避免重新声明常量(如果它们已经被前一次运行声明)
  5. 从(3)
  6. 重复

    firebug输出:

    //FIRST RUN::
    >>> console.group() console.info('--code start--'); ...console.info('--code end--'); console.groupEnd()
    --code start--
    chk_constsDeclaredYet = undefined
    foo = undefined
    --if()--
    --if() running..--
    --end if()--
    chk_constsDeclaredYet = true
    foo = bar
    --code end--
    
    //SECOND RUN::
    >>> console.group() console.info('--code start--'); ...console.info('--code end--'); console.groupEnd()
    TypeError: redeclaration of const foo { message="redeclaration of const foo", more...}
    

3 个答案:

答案 0 :(得分:4)

这是一个老问题的答案。我写了一个slightly newer answer处理类似的“const重新赋值/范围”问题,其中我表明所产生的错误(如果有的话)因执行方法浏览器而异。

由于const(不是ECMAScript第5版标准的一部分)将在ECMAScript第6版中具有不同的含义,我建议在当前代码中避免使用 。 / p>


const,与var一样,是“功能范围”。我怀疑问题来自var上与绑定相同类型的“to top of function”促销(这解释了为什么异常没有来自作业,但来自宣言)。也就是说,任何后续的const x = ...无论它们出现在哪里,都被认为是无效的,因为先前的声明已经存在(根据定义,只能有给定名称的一个const)每个范围)。但是,const可以采用任何值,因此分配const x = ...网站上发生,就像在var x = ...网站上进行分配一样,即使注释也是如此/ binding被提升到范围的顶部。

这是一个简单的测试用例,可以更清楚地说明问题:

function x () { if (true) { const a = 1 } else { const a = 2 }}
// => TypeError: redeclaration of const a @ <x-jsd:interactive-session

如您所见,错误发生在函数执行时的函数声明处。这就是try / catch不起作用的原因。行为也可能受到您正在处理的交互式工具的影响,具体取决于它执行代码的方式(例如,每次都是相同的执行上下文?)。

但是,这样做很好,并强化了上面的初始命题:

(function x() { if (false) { const c = 1 }; return c })()
// => undefined

来自https://developer.mozilla.org/en/JavaScript/Reference/Statements/const

(大胆加重)

  
    

创建一个常量,该常量可以是声明它的函数的全局或局部。 常量遵循与变量相同的范围规则。

         

常量的值不能通过重新赋值来改变,并且不能重新声明常量。因此,尽管可以在不初始化的情况下声明常量,但这样做是没用的。

         

常量不能与同一范围内的函数或变量共享其名称。

         

const是一个特定于Mozilla的扩展,IE不支持它,但自9.0版和Safari版以来,Opera已部分支持它。

  

答案 1 :(得分:1)

const类型应始终等于常量值。如果if语句可以更改常量的值,则它应该是var,因为它的值可能会有所不同。

但您遇到的问题似乎是因为您将常量值设置为两次。您在代码第一次运行时初始化常量。由于常量在再次运行时具有值,因此会出现异常。如果将const foo = 'bar';移到脚本顶部,则不会发现该问题。但是,如果您希望根据逻辑更改该值,则需要var

修改

如果您阅读了异常消息,则会显示“重新声明const foo”。这意味着你不能两次声明foo。现在在控制台中,每次运行代码(没有刷新)时,先前的变量仍然在范围内。所以从理论上讲,即使你只在代码中看到一次,你也会多次声明const foo。你不能将它包装在if / else块中,因为它仍然需要const foo ='bar',这仍然是一个非法声明。

您可能不得不在运行更改的代码之间刷新页面。

答案 2 :(得分:0)

我不知道这是不是最好的方法,但是eval会让你解决这个问题:

if( !chk_constsDeclaredYet ){ eval("const foo = \"bar\"") }