广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >JS中的Error对象及使用JSON.stringify()序列化Error问题
  • 814
分享到

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

2024-04-02 19:04:59 814人浏览 安东尼
摘要

目录一. 错误对象的类型错误处理二.使用JSON.stringfy()去序列化一个 ErrorMDN 定义对象属性的 enumerablejsON.stringify() 的第二个参

一. 错误对象的类型

  • Error: 所有错误类型的父类型;
  • SyntaxError: 语法错误,表示程序的语法使用错误;
console.log(" "" ") ;
// Uncaught SyntaxError: missing ) after argument list
  • ReferenceError: 引用错误,表示引用的变量不存在;
console.log(a);
// Uncaught ReferenceError: a is not defined
  • TypeError: 类型错误,表示使用了错误的数据类型
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 之后的代码本来就会执行
}
  • 放在try...catch中的代码,执行效率会降低;
  • 尽量少的将代码放入try...catch中;
  • 如果可提前预知错误原因,可用 if...else 代替,提前预防错误。

抛出错误 throw error

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

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

错误对象的属性:

  • name属性: 错误类型;
  • message属性: 错误相关的描述信息;
  • stack 属性:函数调用栈记录信息(错误相关信息,错误出现的位置)
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格式:

  • 转换值如果有toJSON()方法,该方法定义什么值将被序列化。
  • 数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中。
  • 布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。
  • undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。函数、undefined被单独转换时,会返回undefined,如JSON.stringify(function(){}) or JSON.stringify(undefined).
  • 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
  • 所有以 symbol 为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。
  • Date日期调用了toJSON()将其转换为了string字符串(同Date.toISOString()),因此会被当做字符串处理。
  • NaN和Infinity格式的数值及null都会被当做null。
  • 其他类型的对象,包括Map/Set/weakMap/weakSet,仅会序列化可枚举的属性。

“仅会序列化可枚举的属性”,是什么意思呢?众所周知,在 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]])
  • value
  • 将要序列化成 一个JSON 字符串的值。
  • replacer 可选
  • 如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;如果该参数为null或者未提供,则对象所有的属性都会被序列化。
  • space 可选
  • 指定缩进用的空白字符串,用于美化输出(pretty-print);如果参数是个数字,它代表有多少的空格;上限为10。该值若小于1,则意味着没有空格;如果该参数为字符串(字符串的前十个字母),该字符串将被作为空格;如果该参数没有提供(或者为null)将没有空格。
  • 返回值 节
  • 一个表示给定值的JSON字符串。

我们来看 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"
// }"

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

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

本文链接: https://www.lsjlt.com/news/166376.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作