一. 错误对象的类型

  • 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"
// }"

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

JS中的Error对象及使用JSON.stringify()序列化Error问题的更多相关文章

  1. html5 拖拽及用 js 实现拖拽功能的示例代码

    这篇文章主要介绍了html5 拖拽及用 js 实现拖拽,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. ios – 如何使用AVCaptureVideoDataOutput录制视频

    使用AVCaptureSession获取相机输出,并成功添加了音频和视频输入和输出.使用AVCaptureMovieFileOutput可以使用照片库中的输出视频保存但是我使用AVCaptureVideoDataOutput作为输出,以便从代理人获取的元数据进行额外的工作,并尝试录制视频,但无法获取任何方法来开始和停止录制视频.建议如何使用AVCaptureVideoDataOutput录制视频解

  4. ios – 允许用户在swift 2.0中播放背景音乐

    我正在寻找一些代码,允许用户在使用我的应用程序的同时从手机播放音乐.以前在swift2.0之前,我会把它放在应用程序委托中,它会很好的工作:有谁知道如何在swift2.0中实现?解决方法以下将是Swift2在AVSession上调用setCategory和setActive的语法:要么

  5. ios – CGPath和UIBezierPath()有什么区别?

    目前,我正在努力制作一个自定义按钮,我有一个图像,并具有坐标,但我发现您可以通过使用CGPath类或UIBezierPath创建一个按钮/对象类.有人可以告诉我两者有什么区别?解决方法CGPath是CoreGraphics库的不透明类型,而UIBezierPath是UIKit中的Obj-C类.UIBezierPath是一个围绕CGPath的包装,具有更加面向对象的界面和一些方便的方法.使用CGPath可能会略微更快,因为它不必经过Obj-C,并且它具有更高级的功能,如CGPathApply.重要的是,UI

  6. ios – 在网络视图中播放视频意外结束了背景视频录制?

    我正在使用WKWebView在我的应用程序中显示全屏YouTube视频,并使用AVCaptureSession在YouTube上浏览和播放视频时在后台录制音频和视频.按下按钮时捕获会话开始.但是,在录制过程中,当选择YouTube视频并开始全屏播放时,它会立即意外结束录制,因为会调用处理录制结束的委托方法.请有人向我解释如何解决这个问题?

  7. swift皮筋弹动发射飞机ios源码

    这是一个款采用swift实现的皮筋弹动发射飞机游戏源码,游戏源码比较详细,大家可以研究学习一下吧。

  8. swift 快速奔跑的兔几 本节的内容是:序列化与反序列化

    在cocoa中,我们经常需要向磁盘保存数据块,cocoa将这些数据块表示为NSData对象例如,有一个字符串,将其转换为NSData,可以使用如下方法:我们还可以将对象转化为数据。遵守协议NSCoding的对象可以转换为NSData对象,也可以从NSData对象中加载,方法如下:

  9. Swift中一个类中的枚举enum类型的数据该如何实现序列化NSCoder

    简述昨天在开发中遇到了这样一个问题,需要用NSUserDefaults持久化一些数据,其中需要保存一个自己定义的类对象。结束其实枚举本来就是一个Int,因此我们将其声明为Int型就可以根据Int值初始化了,以此实现序列化和反序列化。

  10. swift json的序列化和反序列化

    还有一点东西没写完,权作笔记参考:http://www.hangge.com/blog/cache/detail_983.html

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部