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.
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.
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.
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 ...
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.
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.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With