throw

throw 语句引发用户定义的异常。当前函数的执行将停止(throw 之后的语句将不会被执行),并且控制权将被传递到调用堆栈中的第一个 catch 块。如果调用者函数中不存在 catch 块,则程序将终止。

¥The throw statement throws a user-defined exception. Execution of the current function will stop (the statements after throw won't be executed), and control will be passed to the first catch block in the call stack. If no catch block exists among caller functions, the program will terminate.

Try it

语法

¥Syntax

js
throw expression;
expression

要抛出的表达式。

描述

¥Description

throw 语句在可以使用语句的所有上下文中均有效。它的执行会生成一个穿透调用堆栈的异常。有关错误冒泡和处理的更多信息,请参阅 控制流程和错误处理

¥The throw statement is valid in all contexts where statements can be used. Its execution generates an exception that penetrates through the call stack. For more information on error bubbling and handling, see Control flow and error handling.

throw 关键字后面可以跟任何类型的表达式,例如:

¥The throw keyword can be followed by any kind of expression, for example:

js
throw error; // Throws a previously defined value (e.g. within a catch block)
throw new Error("Required"); // Throws a new Error object

实际上,你抛出的异常应该始终是 Error 对象或 Error 子类的实例,例如 RangeError。这是因为捕获错误的代码可能期望某些属性(例如 message)出现在捕获的值上。例如,Web API 通常会抛出 DOMException 实例,该实例继承自 Error.prototype

¥In practice, the exception you throw should always be an Error object or an instance of an Error subclass, such as RangeError. This is because code that catches the error may expect certain properties, such as message, to be present on the caught value. For example, web APIs typically throw DOMException instances, which inherit from Error.prototype.

自动插入分号

¥Automatic semicolon insertion

该语法禁止 throw 关键字和要抛出的表达式之间的行终止符。

¥The syntax forbids line terminators between the throw keyword and the expression to be thrown.

js
throw
new Error();

上面的代码经过 自动分号插入 (ASI) 转化为:

¥The code above is transformed by automatic semicolon insertion (ASI) into:

js
throw;
new Error();

这是无效代码,因为与 return 不同,throw 后面必须跟一个表达式。

¥This is invalid code, because unlike return, throw must be followed by an expression.

为了避免这个问题(防止 ASI),你可以使用括号:

¥To avoid this problem (to prevent ASI), you could use parentheses:

js
throw (
  new Error()
);

示例

¥Examples

抛出用户定义的错误

¥Throwing a user-defined error

此示例定义了一个函数,如果输入不是预期类型,则该函数将抛出 TypeError

¥This example defines a function that throws a TypeError if the input is not of the expected type.

js
function isNumeric(x) {
  return ["number", "bigint"].includes(typeof x);
}

function sum(...values) {
  if (!values.every(isNumeric)) {
    throw new TypeError("Can only add numbers");
  }
  return values.reduce((a, b) => a + b);
}

console.log(sum(1, 2, 3)); // 6
try {
  sum("1", "2");
} catch (e) {
  console.error(e); // TypeError: Can only add numbers
}

抛出一个现有的对象

¥Throwing an existing object

此示例调用基于回调的异步函数,并在回调收到错误时引发错误。

¥This example calls a callback-based async function, and throws an error if the callback receives an error.

js
readFile("foo.txt", (err, data) => {
  if (err) {
    throw err;
  }
  console.log(data);
});

以这种方式抛出的错误无法被调用者捕获,并且将导致程序崩溃,除非 (a) readFile 函数本身捕获错误,或者 (b) 程序在捕获顶层错误的上下文中运行。你可以使用 Promise() 构造函数更自然地处理错误。

¥Errors thrown this way are not catchable by the caller and will cause the program to crash unless (a) the readFile function itself catches the error, or (b) the program is running in a context that catches top-level errors. You can handle errors more naturally by using the Promise() constructor.

js
function readFilePromise(path) {
  return new Promise((resolve, reject) => {
    readFile(path, (err, data) => {
      if (err) {
        reject(err);
      }
      resolve(data);
    });
  });
}

try {
  const data = await readFilePromise("foo.txt");
  console.log(data);
} catch (err) {
  console.error(err);
}

规范

Specification
ECMAScript Language Specification
# sec-throw-statement

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看

¥See also