javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JS Error对象及JSON.stringify()序列化Error

JS中的Error对象及使用JSON.stringify()序列化Error问题

作者:阿斯巴甜嘛

这篇文章主要介绍了JS中的Error对象及使用JSON.stringify()序列化Error问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

一. 错误对象的类型

console.log(" "" ") ;
// Uncaught SyntaxError: missing ) after argument list
console.log(a);
// Uncaught ReferenceError: a is not defined
let a;
console.log(a.name);
// Uncaught TypeError: Cannot read properties of undefined (reading 'name')
RangeError:范围错误, 数据值不在其所允许的范围内(函数递归调用容易出现此错误)

// 保留小数点多少位
(10.24).toFixed(-1);  // toFixed() digits argument must be between 0 and 100
URIError: URI错误,向全局 URI 处理函数(decodeURI、decodeURIComponent)传递一个不合法的URI时,URIError 错误会被抛出

// 解码URI地址   错误:格式不正确
console.log(decodeURI("%") );   // URIError: URI malformed

以上都是不同错误类型的 Error构造函数,能通过new 创建错误对象

错误处理

捕获错误 try ... catch

try {
    // 正常书写的程序代码(可能会出错的代码)
} catch (err) {
    // err: try中执行语句发生错误时,自动创建err错误对象,并将错误信息保存在对象err中
    // 执行错误处理
} finally {
    // 一般用于释放资源
    // finally 可有可无,因为try ... catch 之后的代码本来就会执行
}

抛出错误 throw error

通过throw,主动抛出异常错误;

throw new Error("错误信息");

错误对象的属性:

try{
    console.log(a);    
} catch (err) {
    console.log(err.name);        // ReferenceError
    console.log(err.message);     // a is not defined
}

二.使用JSON.stringfy()去序列化一个 Error

最近在做Node 服务端 测试的时候,遇到 打log JSON.stringify(error)为{}的问题,这样的情况导致根本无法定位到具体问题。

例如: 

JSON.stringify(): 它能够方便地把一个对象转化成字符串;

但是,它也有一个较大的缺点,就是无法直接处理如Error 这类的对象。

const err = new Error('This is an error')
JSON.stringify(err)
// '{}'

在控制台运行上述代码后会发现,JSON.stringify() 的结果是一个字符串的 "{}",里面没有任何有效内容。这是否意味着 JSON.stringify() 确实无法处理 Error 呢?下面我们来看看在 MDN 里这个函数是如何定义的。

MDN 定义

JSON.stringify()将值转换为相应的JSON格式:

“仅会序列化可枚举的属性”,是什么意思呢?众所周知,在 JS 的世界中一切皆对象,对象有着不同的属性,这些属性是否可枚举,我们用 enumerable 来定义.

对象属性的 enumerable

举个例子,我们用 obj = { a: 1, b: 2, c: 3 } 来定义一个对象,然后设置它的 c 属性为“不可枚举”,看看效果会如何:

首先看处理前的效果:

const obj = {a: 1,b: 2,c: 3};
JSON.stringify(obj)
// '{"a":1,"b":2,"c":3}'

再看处理后的效果:

const obj = { a: 1, b: 2, c: 3 }
 
Object.defineProperty(obj, 'c', {
  value: 3,
  enumerable: false
})
 
JSON.stringify(obj)
 
// => "{"a":1,"b":2}"

可以看到,在对 c 属性设置为不可枚举以后,JSON.stringify() 便不再对其进行序列化。

我们把问题再深入一些,有没有办法能够获取一个对象中包含不可枚举在内的所有属性呢?答案是使用 Object.getOwnPropertyNames() 方法。

依然是刚刚被改装过的 obj 对象,我们来看看它所包含的所有属性:

Object.getOwnPropertyNames(obj)
 
// => ["a", "b", "c"]

不可枚举的 c 属性也被获取到了!

用同样的方法,我们来看看一个 Error 都包含哪些属性:

const err = new Error('This is an error')
Object.getOwnPropertyNames(err)
 
// => ["stack", "message"]

可以看到,Error 包含了 stack 和 message 两个属性,它们均可以使用点运算符 . 从 err 实例里面拿到。

既然我们已经能够获取 Error 实例的不可枚举属性及其内容,那么距离使用 JSON.stringify() 序列化 Error 也已经不远了!

JSON.stringify() 的第二个参数

JSON.stringify() 可以接收三个参数:

语法:

JSON.stringify(value[, replacer [, space]])

我们来看 replacer 的用法: 

 ……如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中……

依然使用上文的 obj 为例子:

const obj = { a: 1, b: 2, c: 3 }
 
Object.defineProperty(obj, 'c', {
  value: 3,
  enumerable: false
})
 
JSON.stringify(obj, ['a', 'c'])
 
// => "{"a":1,"c":3}"

可以看到,我们在 replacer 中指定了要序列化 a 和 c 属性,输出结果也是只有这两个属性的值,且不可枚举的 c 属性也被序列化了!守得云开见月明,Error 对象被序列化的方法也就出来了:

const err = new Error('This is an error')
 
JSON.stringify(err, Object.getOwnPropertyNames(err), 2)
 
// => 
// "{
//   "stack": "Error: This is an error\n    at <anonymous>:1:13",
//   "message": "This is an error"
// }"

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文