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

发布于 2024-10-02 03:34:46 字数 1180 浏览 2 评论 0原文

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

我尝试将其包装在 try{}catch(e){} 块中,但这并没有帮助,即使尝试使用以下代码绕过它(发布减去所有控制台) .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)

萤火虫输出:

//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:

  1. paste code into firebug console
  2. hit run (creating constants)
  3. i make an edit to the code in the console without reloading the page (the constants are still defined in the page context)
  4. hit run again (using the if(){} to avoid redeclaring the constants if they've already been declared by the previous run)
  5. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

愁杀 2024-10-09 03:34:46

这是一个古老的答案。我写了一个稍新的答案处理类似的“const重新分配” /scope”问题,我显示产生的错误(如果有)因执行方法和浏览器而异。

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


constvar 一样是“函数作用域”。我怀疑这个问题是由绑定上与var发生的相同类型的“到函数顶部”提升引起的(这解释了为什么异常不是来自赋值而是来自声明)。也就是说,任何后续的 const x = ...无论出现在哪里,都被认为是无效的,因为先前的声明已经存在(根据定义,只能有 < em>每个范围有一个给定名称的常量)。但是,const 可以采用任何值,因此赋值发生在 const x = ... 站点,就像赋值发生在var x = ... 站点,即使注释/绑定已提升到范围的顶部。

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

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 版本以来 Opera 和 Safari 已部分支持。

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, like var is "function-scoped". I suspect the problem arises from the same kind of "to top of function" promotion on the binding that happens with var (this explains why the exception does not come from the assignment but from the declaration). That is, any subsequent const 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 the const x = ... site, just as the assignment occurs at the var 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:

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

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:

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

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

(Bold Emphasis added)

Creates a constant that can be global or local to the function in which it is declared. Constants follow the same scope rules as variables.

The value of a constant cannot change through re-assignment, and a constant cannot be re-declared. Because of this, although it is possible to declare a constant without initializing it, it would be useless to do so.

A constant cannot share its name with a function or a variable in the same scope.

const is a Mozilla-specific extension, it is not supported by IE, but has been partially supported by Opera since version 9.0 and Safari.

青柠芒果 2024-10-09 03:34:46

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 an if statement can change the value of a constant, it should probably be a var, 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 a var.

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.

奢欲 2024-10-09 03:34:46

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

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

I don't know if this is the best way, but eval will let you get around that:

if( !chk_constsDeclaredYet ){ eval("const foo = \"bar\"") }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文