Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does re-declaring an argument inside of a try/catch throw a ReferenceError?

Tags:

javascript

I mistakenly wrote a re-declaration of an argument as a const in a function and instead of throwing SyntaxError: Identifier 'bar' has already been declared I ended up with ReferenceError: bar is not defined..

What causes this behaviour? It wasn't the expected error, and left me confused for a few minutes.

Example code:

function foo(bar) {   try {       console.log(bar);       const bar = 123;   } catch(err) { console.log(err) } } foo(456); 

If I don't wrap the declaration in a try/catch, I get (what I believe to be) the expected error.

like image 923
rlemon Avatar asked Jan 17 '18 15:01

rlemon


People also ask

Why do I get an error when I use catch arguments?

The compiler produces an error if you order your catch blocks so that a later block can never be reached. Using catch arguments is one way to filter for the exceptions you want to handle. You can also use an exception filter that further examines the exception to decide whether to handle it.

What is the use of throw error in try catch?

One of the benefits of try/catch is its ability to display your own custom-created error. This is called (throw error). In situations where you don't want this ugly thing that JavaScript displays, you can throw your error (an exception) with the use of the throw statement. This error can be a string, boolean, or object.

What is try catch catch finally in Java?

Try, Catch, Finally In Java Keyword Description Try We specify the block of code that might ... Catch When the exception is raised it needs to ... Finally Sometimes we have an important code in o ... Throw The keyword “throw” is used to throw the ... 1 more rows ...

How does the catch block handle all types of errors?

The error throwing on line (*) from inside catch block “falls out” of try...catch and can be either caught by an outer try...catch construct (if it exists), or it kills the script. So the catch block actually handles only errors that it knows how to deal with and “skips” all others.


2 Answers

Constants are block-scoped, much like variables defined using the let statement.

From this MDN article.

Since you wrapped bar inside a block of braces, its definition is relative to that block. And because you have another bar declaration inside of that block, despite being after the call to it, the compiler will attempt to use this newly defined bar instead of the passed-in parameter. Rename them as separate parameters to mitigate confusion, since one can assume they are holding different data because of your declaration.

like image 190
Marcus Parsons Avatar answered Oct 07 '22 11:10

Marcus Parsons


It's a myth that const and let aren't hoisted at all. They're half-hoisted. :-) That is: Within a block, if const bar or let bar (or class bar { } for that matter) appears anywhere in that block, then bar cannot be used prior to that declaration in the block — even if it exists in a containing scope. This area between the beginning of the block and the declaration is called the Temporal Dead Zone:

function foo(bar) {   // `bar` is fine here   try {       // Temporal Dead Zone, `bar` cannot be used here       console.log(bar);       // End of TDZ       const bar = 123;       // `bar` would be fine here   } catch(err) { console.log(err) } } foo(456);     
like image 22
T.J. Crowder Avatar answered Oct 07 '22 13:10

T.J. Crowder