> For the complete documentation index, see [llms.txt](https://1425816423.gitbook.io/my-knowledge-base/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://1425816423.gitbook.io/my-knowledge-base/qian-duan-ji-shu/javascript/javascript-error.md).

# JavaScript Error

## Error类型

### Error类型

ECMAScript定义了几种错误类型：

* `Error` ： 所有错误类型的基类，其他错误类型都继承该类型。
* `[EvalError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/EvalError)` ： 创建一个 error 实例，表示错误的原因：与 `[eval()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval)` 有关。
* `[RangeError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RangeError)` ：创建一个 error 实例，表示错误的原因：数值变量或参数超出其有效范围。
* `[ReferenceError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError)` ：创建一个 error 实例，表示错误的原因：无效引用。
* `[SyntaxError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError)` ：创建一个 error 实例，表示错误的原因：语法错误。
* `[TypeError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypeError)` ：创建一个 error 实例，表示错误的原因：变量或参数不属于有效类型。
* `[URIError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/URIError)` ：创建一个 error 实例，表示错误的原因：给 `[encodeURI()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURI)` 或 `[decodeURI()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/decodeURI)` 传递的参数无效。
* `[AggregateError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/AggregateError)` ： 创建一个 error 实例，其中包裹了由一个操作产生且需要报告的多个错误。如：`[Promise.any()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/any)` 产生的错误。
* `[InternalError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/InternalError)` 非标准： 创建一个代表 Javascript 引擎内部错误的异常抛出的实例。如：递归太多。

### 识别Error类型

不同的错误类型可用于为异常提供更多信息，以便实现适当的错误处理逻辑，如果你需要识别错误类型，可以在catch块中通过instanceof来判断error对象的类型。

```jsx
try{ 
	const a = 1;
	a = 2;
}catch(error){
	console.log(error instanceof TypeError);
	// true
}
```

### 抛出错误

**抛出错误需要用到throw操作符，它可以抛出任何值，并且js一旦执行throw语句，就会立即停止执行，除非try…catch语句捕捉了抛出的异常。**

```jsx
// throw抛出的值类型不限
throw 1
throw '1'
throw {a: 1}
throw true
```

但是通常我们最好抛出一个错误对象来模拟浏览器错误，抛出一个错误对象比直接抛出一个值(例如字符串)更好的地方在于前者会包含调用栈等信息，以便后续修复异常。

```jsx
(function(){
	let a = 123; 
	throw new Error(123)  
})()

/*
VM2736:1 Uncaught Error: 123
    at <anonymous>:1:32
    at <anonymous>:1:50
(匿名) @ VM2736:1
(匿名) @ VM2736:1
*/
```

抛出一个错误对象很简单，只需要通过实例化一个内置错误类即可，通常是Error，因为其他的错误类都是继承于Error，你只需要传递一个参数message，即错误消息。message是可选的，但是通常我们都会传，以便更好地处理错误。

```jsx
function sort(arr){
	if(!Array.isArray(arr)){ 
		throw new Error('参数类型错误，你应当传递一个数组类型')
	}
	return arr.sort((a,b)=> a-b);
}
sort(1);
// Uncaught Error: 参数类型错误，你应当传递一个数组类型
```

当然你也可以抛出一个具体的错误对象，例如上面这里例子中使用TypeError可以更好地表示是类型错误。

```jsx
throw new TypeError('你应当传递一个数组类型')
// Uncaught TypeError: 你应当传递一个数组类型
```

除了Error和其他内置错误对象，你还可以自定义Error类型。

## 自定义Error类型

创建一个自定义Error类型很简单，只需要实现一个继承Error的类，并实现message属性和name属性即可。

```jsx
class CustomError extends Error {
  constructor(name='CustomError ', message) {
    super();

    this.name = name;
    this.message = message;
  }
}
```

示例:

下面这个实例中实现了一个自定义Error类型CustomError，在输入框中输入CustomError.name和CustomError.message后点击抛出异常按钮，你应当可以在控制台看到错误信息。

<https://codesandbox.io/s/zi-ding-yi-cuo-wu-lei-xing-nj0c9g>

## 捕获异常

### try…catch…finally

try…catch可以捕获异常，**当try块中发生错误时，代码会立即退出执行，并跳到catch块中执行，catch块此时会接收到一个错误对象**，该错误对象包含错误的相关信息，**这个错误对象中的信息根据浏览器而异，但是它至少会包含message属性。**

```jsx
try{
	const a = 1;
	a++; // 产生一个错误
	console.log(1)  // 不会执行
}catch(err){ 
	// 错误对象是必须要声明的，即使你不用它
}
```

finally块是可选的，无论是否发生错误，finally块的代码都会执行，并且**try或catch块都无法阻止finally块的执行。**

```jsx
function fn(){ 
	try{
		return 1;
	}catch(err){
		return 2;
	}finally{ 
		console.log(3)
	}
}

fn() // 3
```

### window\.onerror

任何没有被try…catch捕获的异常都会传递到window\.onerror事件上，在onerror事件处理程序上通常有这么几个参数：

1. 错误消息message
2. 错误文档的URL
3. 错误发生的行号
4. 错误发送的列号
5. 错误对象

如果window\.onerrror事件处理程序中返回为true，那么控制台将不会打印错误信息，即：

```jsx
window.onerror = function (message, url, lno, cno, error) {
    console.table({
        message,
        url,
        lno,
        cno,
        error
    });
    return true;
}
```

window\.onerror是处理错误的最后一道防线，可以在此将异常上报，以便后续追踪修复。

更多信息见：[前端监控方案](https://www.notion.so/c4b9e1a1a77f4007b63ab623b6c62433?pvs=21)

## 新特性

### Error Cause

Error Cause当前已经到达第四阶段，**Error Cause的作用是在从深层内部逻辑引发的错误时，能够将错误对象一同抛出，以此来增强错误描述。**

可以看下这个例子：

```jsx
// 私有函数
function _sort(arr) {
    return arr.sort((a, b) => a - b)
}

export function sort(arr) {
    // ... 处理某些逻辑
    try {
        _sort(arr)
    } catch (err) {
        throw new Error('执行sort错误，原因是'+ err.message)
    }
}

sort(1)
// Uncaught Error: 执行sort错误，原因是arr.sort is not a function
```

在这个例子中，我们提前预见`_sort`函数的执行可能会出现异常，因此我们用try…catch捕获异常，但是我们并不能提前预判是哪种异常，因此我们只能提示有错误，并将错误消息(即`err.message`)一同显示。但是这种并不是很友好，因为err错误对象只有错误消息被传递，由于错误是深层的，错误堆栈不会追踪到`_sort`函数，除非我们去`_sort`函数源码，否则我们很难判断错误发送的原因，但是Error Cause能够将错误对象一同携带出来，我们可以通过错误对象的错误堆栈来快速地追踪到错误。

使用error cause很简单，只需要在Error实例化时第二个参数传递一个包含cause属性的对象，而cause属性的值就是错误对象。

```jsx
function _sort(arr) {
    return arr.sort((a, b) => a - b)
}

function sort(arr) {
    // ... 处理某些逻辑
    try {
        _sort(arr)
    } catch (err) {
        throw new Error('执行sort错误', {
            cause: err
        })
    }
}

sort(1)
```

```jsx
Uncaught Error: 执行sort错误
    sort http://127.0.0.1:5500/error.html:75
    <anonymous> http://127.0.0.1:5500/error.html:81
Caused by: TypeError: arr.sort is not a function
    _sort http://127.0.0.1:5500/error.html:67
    sort http://127.0.0.1:5500/error.html:73
    <anonymous> http://127.0.0.1:5500/error.html:81
```

当使用Error Cause后，`_sort`函数错误堆栈也能被打印出来，可以很快的锁定错误。

## 参考

《JavaScript高级程序设计第四版》

[Window: error event - Web API 接口参考 | MDN (mozilla.org)](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/error_event)

[Error - JavaScript | MDN (mozilla.org)](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error#%E6%8F%8F%E8%BF%B0)

[Error() constructor - JavaScript | MDN (mozilla.org)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Error)

<https://github.com/tc39/proposal-error-cause>
