throw
throw 语句会抛出一个用户定义的异常。当前函数的执行将停止(throw 之后的语句不会被执行),控制将传递到调用堆栈中第一个 catch 块。如果在调用函数中不存在 catch 块,程序将终止。
试一试
function getRectArea(width, height) {
  if (isNaN(width) || isNaN(height)) {
    throw new Error("Parameter is not a number!");
  }
}
try {
  getRectArea(3, "A");
} catch (e) {
  console.error(e);
  // Expected output: Error: Parameter is not a number!
}
语法
js
throw expression;
- 表达式
- 
要抛出的表达式。 
描述
throw 语句在所有可以使用语句的上下文中都有效。它的执行会产生一个穿透调用堆栈的异常。有关错误冒泡和处理的更多信息,请参阅控制流和错误处理。
throw 关键字后面可以跟任何类型的表达式,例如
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。
自动分号插入
语法禁止 throw 关键字和要抛出的表达式之间存在行终止符。
js
throw
new Error();
上面的代码通过自动分号插入 (ASI) 转换为
js
throw;
new Error();
这是无效代码,因为与 return 不同,throw 后面必须跟一个表达式。
为了避免这个问题(防止 ASI),你可以使用括号
js
throw (
  new Error()
);
示例
抛出用户定义的错误
此示例定义了一个函数,如果输入不是预期类型,则会抛出 TypeError。
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
}
抛出现有对象
此示例调用一个基于回调的异步函数,并在回调收到错误时抛出错误。
js
readFile("foo.txt", (err, data) => {
  if (err) {
    throw err;
  }
  console.log(data);
});
以这种方式抛出的错误不能被调用者捕获,并且会导致程序崩溃,除非 (a) readFile 函数本身捕获了错误,或 (b) 程序在捕获顶级错误的上下文中运行。你可以通过使用 Promise() 构造函数更自然地处理错误。
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);
}
规范
| 规范 | 
|---|
| ECMAScript® 2026 语言规范 # sec-throw-statement | 
浏览器兼容性
加载中…