开发者

Why is const throwing an error on multiple runs of the code when inside an if() or try{}catch(e){}?

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()
开发者_Go百科TypeError: redeclaration of const foo { message="redeclaration of const foo", more...}


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.


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.


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\"") }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜