为什么 const 在 if() 或 try{}catch(e){} 内多次运行代码时会抛出错误?
我正在尝试使用 const 声明一堆常量。我的问题是,在 Firebug 控制台中测试代码会引发错误,抱怨“const foo 的重新声明”。
我尝试将其包装在 try{}catch(e){}
块中,但这并没有帮助,即使尝试使用以下代码绕过它(发布减去所有控制台) .info()“调试”要求清晰)第二次运行时它仍然会抛出错误:
if(!chk_constsDeclaredYet) {
var chk_constsDeclaredYet = true;
const foo="bar";
}
我的问题是,虽然 const 位于 if(){} 内,但当代码第二次“运行”时,为什么 const foo 甚至被关注?
注意:代码将在 firebug javascript 控制台内运行,我想要实现的工作流程是:
- 将代码粘贴到 firebug 控制台中
- 点击运行(创建常量)
- 我对代码进行编辑控制台而不重新加载页面(常量仍然在页面上下文中定义)
- 再次点击运行(使用 if(){} 以避免重新声明常量,如果它们已经在上一次运行中声明过)
- 重复(3)
萤火虫输出:
//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...}
I'm trying to declare a bunch of constants using const
. My problem is that testing the code in the Firebug console throws an error complaining about the 'redeclaration of const foo'.
I've attempted wrapping it in a try{}catch(e){}
block but that didn't help, and even when trying to get around it using the following code (posted minus all the console.info() "debugging" calls for clarity) it still throws the error when run for the second time:
if(!chk_constsDeclaredYet) {
var chk_constsDeclaredYet = true;
const foo="bar";
}
My question is that while the const is within the if(){}, when the code is 'run' for the second time, why is const foo being even being looked at?
NB: the code is to be run inside the firebug javascript console and the workflow i'm trying to achieve is:
- paste code into firebug console
- hit run (creating constants)
- i make an edit to the code in the console without reloading the page (the constants are still defined in the page context)
- hit run again (using the if(){} to avoid redeclaring the constants if they've already been declared by the previous run)
- repeat from (3)
firebug output:
//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...}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是一个古老的答案。我写了一个稍新的答案处理类似的“const重新分配” /scope”问题,我显示产生的错误(如果有)因执行方法和浏览器而异。
由于 const(不是 ECMAScript 第 5 版标准的一部分)在 ECMAScript 6 版中具有不同的含义,因此我建议在当前代码中避免使用它。
const
与var
一样是“函数作用域”。我怀疑这个问题是由绑定上与var
发生的相同类型的“到函数顶部”提升引起的(这解释了为什么异常不是来自赋值而是来自声明)。也就是说,任何后续的const x = ...
,无论出现在哪里,都被认为是无效的,因为先前的声明已经存在(根据定义,只能有 < em>每个范围有一个给定名称的常量)。但是,const
可以采用任何值,因此赋值发生在const x = ...
站点,就像赋值发生在var x = ...
站点,即使注释/绑定已提升到范围的顶部。这是一个简单的测试用例,可以更清楚地演示问题:
如您所见,错误发生在函数声明处,而错误发生在函数执行处。这就是 try/catch 不起作用的原因。该行为也可能受到您正在处理的交互式工具的影响,具体取决于它执行代码的方式(例如,每次都是相同的执行上下文?)。
然而,这工作得很好,并强化了上面的最初主张:
来自 https://developer .mozilla.org/en/JavaScript/Reference/Statements/const
(添加了粗体强调)
This is an old-ish answer. I wrote a slightly newer answer dealing with similar "const re-assignment/scope" issues where I show that the errors produced, if any, vary by execution method and browser.
Since
const
(which is not part of the ECMAScript 5th edition standard) is slated to have a different meaning in ECMAScript 6th edition, I would recommend avoiding it in current code.const
, likevar
is "function-scoped". I suspect the problem arises from the same kind of "to top of function" promotion on the binding that happens withvar
(this explains why the exception does not come from the assignment but from the declaration). That is, any subsequentconst x = ...
, wherever they appear, are considered to be invalid because a previous declaration already exists (by definition, there can only be one const of a given name per scope). However,const
can take on any value so the assignment happens at theconst x = ...
site, just as the assignment occurs at thevar x = ...
site, even though the annotation/binding was promoted to the top of the scope.Here is a simple test-case which demonstrates the problem more clearly:
As you can see, the error occurs at the function declaration and not at the function execution. This is why the try/catch does not work. The behavior may also be influenced by the interactive tool you are dealing with depending on how it executes the code (e.g. it's the same execution context each time?).
However, this works fine and reinforces the initial proposition above:
From https://developer.mozilla.org/en/JavaScript/Reference/Statements/const
(Bold Emphasis added)
const
类型应始终等于常量值。如果if
语句可以更改常量的值,那么它可能应该是var
,因为它的值可以变化。但您遇到的问题似乎是因为您将常量的值设置了两次。您可以在代码第一次运行时初始化该常量。由于该常量在再次运行时具有值,因此您会得到异常。如果将
const foo = 'bar';
移至脚本顶部,则不会出现该问题。但再一次,如果您希望该值根据逻辑进行更改,您将需要一个var
。编辑
如果您阅读异常消息,它会显示“redeclaration of const foo”。这意味着你不能声明 foo 两次。现在在控制台中,每次运行代码(无需刷新)时,之前的变量仍然在范围内。因此从理论上讲,即使您在代码中只看到一次,您也会多次声明 const foo 。您不能将其包装在 if/else 块中,因为它仍然需要 const foo = 'bar',这仍然是非法声明。
您可能必须在运行更改的代码之间刷新页面。
A
const
type should always equal a constant value. If anif
statement can change the value of a constant, it should probably be avar
, since its value can vary.But the issue you are having appears to be because you are setting the value of a constant twice. You initialize the constant the first time the code runs. Since the constant has a value when it is ran again, you get the exception. If you move the
const foo = 'bar';
to the top of your script, you won't see that problem. But once again, if you want that value to change based on logic, you'll want avar
.Edit
If you read the exception message, it says "redeclaration of const foo". This means you CANNOT declare foo twice. Now in the console, each time you run the code (without refreshing), the previous variables are still in scope. So in theory, you are declaring const foo multiple times even though you only see it once in your code. You can't wrap it in if/else blocks because it still requires const foo = 'bar', which is still an illegal declaration.
You might have to settle for refreshing the page between running your changed code.
我不知道这是否是最好的方法,但是
eval
会让你解决这个问题:I don't know if this is the best way, but
eval
will let you get around that: