9

Today I run into a weird JS bug, working with const inside a try/catch block, and I'd like to better understand what is causing it.

Let's look at a code example, that is worth more than a thousand words:

try {
  const FOO = 'bar';
  console.log('inside:', FOO);
} catch (e) {}
console.log('outside:', FOO);

This will log:

inside: bar
outside: bar

If we switch to "strict mode" though:

'use strict';
try {
  const FOO = 'bar';
  console.log('inside:', FOO);
} catch (e) {}
console.log('outside:', FOO);

Now the same code produces an error:

ReferenceError: FOO is not defined

If we change const with var though:

'use strict';
try {
  var foo = 'bar';
  console.log('inside:', foo);
} catch (e) {}
console.log('outside:', foo);

Then it all works fine again, even in "strict mode":

inside: bar
outside: bar

Can anyone please help me understand why the const assignment is not working inside a try/catch block in "strict mode"?

Thanks!

joews
  • 29,767
  • 10
  • 79
  • 91
Pensierinmusica
  • 6,404
  • 9
  • 40
  • 58

2 Answers2

16

const, as defined by ECMAScript 6, is a block-level variable declaration. You get a ReferenceError because it's not in scope outside of the try.

However, const was introduced in some engines long before ES6, as a immutable counterpart to var, with function-level scope behaviour (and without TDZ). If you're in sloppy mode (which you should not be), you might still experience this as part of your browser's legacy support.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I had no idea about legacy "`const`". MDN footnote: "In earlier versions of Firefox & Chrome and as of Safari 5.1.7 and Opera 12.00, if you define a variable with const, you can still change its value later." – joews Oct 31 '15 at 22:26
  • @joews: yes, it was nothing better than an alias for `var` so that scripts written for FF (in the belief of a standard feature) would at least run without syntax errors in Safari and Opera as well, even if not guaranteeing unassignability. – Bergi Oct 31 '15 at 22:27
  • 1
    "it will continue to work like this " - V8 in Chrome 48 (current Canary) applies block scope in either mode (tested in console/snippet; I can't find a reference). I guess this could change before release. – joews Oct 31 '15 at 22:52
  • 1
    @joews: You're right, engines do shift towards ES5 compliance. It's just a slow process. Fixed wording in my answer. – Bergi Oct 31 '15 at 23:19
  • For the morbidly curious, here is the relevant v8 revision history: https://code.google.com/p/v8/issues/detail?id=2198 – joews Nov 02 '15 at 09:53
4

Your JavaScript runtime has a partial implementation of ES6 const.

ReferenceError is the expected behaviour for your first example, because const is block scoped and you access FOO outside the defining try block.

The engine you are using supports the const syntax, but it only applies block scoping semantics in strict mode.

The current stable Chrome (46) does this. Chrome 48, however, applies block scope with or without strict mode.

var is not block scoped, so your last example works as expected.

joews
  • 29,767
  • 10
  • 79
  • 91