Errors and exceptions
When something goes wrong, JavaScript code can throw: the running function stops at once and an Error object travels down the call stack until a try block catches it, or the script stops. Follow thirteen real lines, root.js, as root(9) returns normally, root(-4) throws a RangeError, catch prints it, and finally runs last.
5 quick questions
Pick an answer to see why. Your score saves with your progress.
01In root.js, root(-4) throws on line 2. Which lines still run after that throw?
throw stops root at once, so line 3 never runs, and the rest of the try block (line 8) is abandoned. Control jumps to catch (line 10), then finally (line 12).
02What does it mean that the engine "unwinds the call stack"?
Each frame is a call that has not finished. A throw abandons them from the top down until one is inside a try; that try's catch receives the error. If none is, the error is uncaught.
03Inside catch (err), what is err?
catch binds the thrown value itself. Here it is the RangeError object, so err.name is "RangeError" and err.message is "n < 0".
04When does a finally block run?
finally runs whether the try block finished normally, threw and was caught, or threw again from catch. That makes it the place for clean-up.
05You call root(-4) with no try anywhere around it. What happens?
With no try on any frame, the stack unwinds to the bottom and the script stops. A browser console shows Uncaught RangeError: n < 0.
Glossary
- Exception
- A value thrown by throw (or by the engine) that stops normal flow until some code catches it.
- throw
- A statement that stops the running function at once and hands a value, usually an Error object, down the call stack.
- Error object
- An object made by new Error(...) or a subtype such as RangeError. It has a name, a message, and in every major engine a stack trace.
- Call stack
- The pile of calls that have not finished yet, one frame per call. A call pushes a frame; a return or a throw pops it.
- try / catch
- try marks code that may throw; if it does, control jumps to catch, which receives the thrown value.
- finally
- A block after try (and catch) that always runs last, whatever happened.
- Uncaught error
- An exception that no try catches. The script stops and the console reports it.
- Built-in errors
- Error types the engine throws itself, such as TypeError, ReferenceError, SyntaxError and RangeError.
Notes and sources
- throw accepts any value, even a number or a string, but throwing an Error object is the convention: it carries a name, a message and a stack trace, and err instanceof Error is true.
- The stack property is not yet part of the ECMAScript standard, but every major engine adds it to Error objects. Its text differs between engines.
- The figure draws the call stack as boxes. The specification calls each frame an execution context; the engine pushes one per function call and pops it when the call returns or is abandoned by a throw.
- If finally itself returns or throws, that replaces whatever the try or catch block was doing, so keep finally for clean-up only.
- new Error("msg", { cause: err }) wraps a lower-level error in a new one and keeps the original as error.cause.
- For built-in errors the engine writes the message itself, and the wording differs between engines: V8 (Chrome, Node) says "undefined is not a function" for undefined(). Only the type (TypeError) is the same everywhere, so the figure shows the message as a placeholder.
- The figure says the global frame "remembers" its catch. That is a simplification: the specification handles try at the level of the statement (a throw completes the try block abruptly and the catch clause runs), not as data stored in the frame.
- The thirteen lines are real. Paste them into a browser console, or save them as root.js and run node root.js. They print 3, RangeError n < 0 and done.
Quiz Unlocks after the last step.