The throw statement in JavaScript
The throw statement is used to create and throw an error, that is, to forcibly stop execution and hand control to the nearest catch block, if there is one. It is the main way for a function to report a situation it cannot handle correctly.
Theory
TL;DR
throw expression;immediately stops the execution of the current function.- JavaScript then looks for the nearest
try...catchto catch that value. - Any value can be thrown: a string, a number, an object. The right choice, though, is
Erroror one of its subclasses. - The subclasses
TypeError,ReferenceError,SyntaxError,RangeErrorandEvalErrormake the nature of the problem explicit. - A
finallyblock always runs, whether or not there was an error.
Quick example
throw new Error("Something went wrong!");When the interpreter meets throw, execution of the current function stops immediately, and JavaScript starts looking for the nearest try...catch block to catch this error. If there is no such block, the error reaches the top of the stack and the program (or the current task) fails.
Syntax and what can be thrown
throw expression;Where expression is any value, though most often it is an error object (Error).
Handling it with try...catch:
try {
throw new Error("Server connection error!");
} catch (error) {
console.log("Caught an error:", error.message);
}Result:
Caught an error: Server connection error!
JavaScript does not require you to throw an error object specifically; you can throw anything:
throw "Just a string";
throw 404;
throw { message: "Data error", code: 123 };By convention, however, it is always better to use Error or its subclasses: only they are guaranteed to carry a name, a message and a stack trace.
Built-in error types
Erroris the base typeTypeErrorReferenceErrorSyntaxErrorRangeErrorEvalError
An example with a specific type:
function divide(a, b) {
if (b === 0) {
throw new RangeError("Division by zero!");
}
return a / b;
}
try {
divide(5, 0);
} catch (err) {
console.error(err.name + ": " + err.message);
}Result:
RangeError: Division by zero!
The chosen error type lets the catch block tell situations apart with err instanceof RangeError and react differently to each.
How it works together with try...catch...finally
try {
console.log("Starting");
throw new Error("Failure!");
} catch (e) {
console.log("Caught:", e.message);
} finally {
console.log("This block always runs");
}Result:
Starting
Caught: Failure!
This block always runsA summary table:
| What it does | Description |
|---|---|
throw | Stops execution and throws an error |
| What can be thrown | Any value (but Error is recommended) |
| Handled by | try...catch |
After throw | Code in the same block does not run |
The finally block | Always runs, even on a throw |
Common mistakes
- Throwing a string instead of an
Error. Thecatchblock then has neithermessagenorstack, and the logs become useless. Writethrow new Error("..."). - Forgetting
new.throw Error("...")still works, becauseErrorcan be called withoutnew, but a custom error class called withoutnewwill not behave as expected. - Expecting code after
throwto run. The remaining statements in the same block are unreachable. - Swallowing the error with an empty
catch. Acatch (e) {}block hides the problem; either handle it or rethrow it withthrow e. - Putting a
returninsidefinally. It overrides both the value being returned and the error being thrown, so the problem silently disappears. - Assuming
try...catchcatches asynchronous errors. A throw insidesetTimeout, or an unhandled promise rejection outside the block, is not caught: for promises you needawaitinside thetry, or a.catch().
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.