Errors

Not only does JavaScript have different subtypes of errors (TypeError, ReferenceError, SyntaxError, etc.), but also the grammar defines certain errors to be enforced at compile time, as compared to all other errors that happen during runtime.

In particular, there have long been a number of specific conditions that should be caught and reported as “early errors” (during compilation). Any straight-up syntax error is an early error (e.g., a = ,), but also the grammar defines things that are syntactically valid but disallowed nonetheless.

Since execution of your code has not begun yet, these errors are not catchable with try..catch; they will just fail the parsing/compilation of your program.

Tip: There’s no requirement in the spec about exactly how browsers (and developer tools) should report errors. So you may see variations across browsers in the following error examples, in what specific subtype of error is reported or what the included error message text will be.

One simple example is with syntax inside a regular expression literal. There’s nothing wrong with the JS syntax here, but the invalid regex will throw an early error:

  1. var a = /+foo/; // Error!

The target of an assignment must be an identifier (or an ES6 destructuring expression that produces one or more identifiers), so a value like 42 in that position is illegal and can be reported right away:

  1. var a;
  2. 42 = a; // Error!

ES5’s strict mode defines even more early errors. For example, in strict mode, function parameter names cannot be duplicated:

  1. function foo(a,b,a) { } // just fine
  2. function bar(a,b,a) { "use strict"; } // Error!

Another strict mode early error is an object literal having more than one property of the same name:

  1. (function(){
  2. "use strict";
  3. var a = {
  4. b: 42,
  5. b: 43
  6. }; // Error!
  7. })();

Note: Semantically speaking, such errors aren’t technically syntax errors but more grammar errors — the above snippets are syntactically valid. But since there is no GrammarError type, some browsers use SyntaxError instead.

Using Variables Too Early

ES6 defines a (frankly confusingly named) new concept called the TDZ (“Temporal Dead Zone”).

The TDZ refers to places in code where a variable reference cannot yet be made, because it hasn’t reached its required initialization.

The most clear example of this is with ES6 let block-scoping:

  1. {
  2. a = 2; // ReferenceError!
  3. let a;
  4. }

The assignment a = 2 is accessing the a variable (which is indeed block-scoped to the { .. } block) before it’s been initialized by the let a declaration, so it’s in the TDZ for a and throws an error.

Interestingly, while typeof has an exception to be safe for undeclared variables (see Chapter 1), no such safety exception is made for TDZ references:

  1. {
  2. typeof a; // undefined
  3. typeof b; // ReferenceError! (TDZ)
  4. let b;
  5. }