阅读 2731

你懂JSON.parse(JSON.stringify(obj))吗???

文章来源于昨天面试的一个问题,你觉得JSON.parse(JSON.stringify(xx))实现深拷贝有什么问题?或者说有什么不适用的场景?
当时回答如果包含函数,则不适用。现在回答感觉low爆。不知其所以然等于不知。

1.首先我们了解一下什么是JSON?

JSON::JavaScript Object Notation,是一种轻量级的数据交互格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。(完全来源于百度,在我眼里其实就是一个字符串,只不过是有特殊标注的字符串)
JSON支持的语法:
    1.简单值:字符串,数值,布尔值,null(特别注意:不支持undefined)
    2.对象:支持有序键值对,每个值可以是复杂类型也可以是简单值
    3.数组:数组值可以是任意类型,包含简单值,对象,甚至其它数组。
JSON没有变量,函数或者对象实例的概念。。。(即js的日期对象,函数,symbol等都无法识别)
复制代码

2.序列化(JSON.stringify)

规则:
    在序列化js对象时,所有函数和原型成员都会有意的在结果中省略。
    此外,值为undefined的任何属性也会被跳过。最终等到的就是所有实例属性均为有效JSON数据类型的表示。
    (注意:如果日期格式使用JSON.stringify后会变成字符串,JSON.parse后也是字符串)
直接放测试图吧:
    
复制代码

image.png

上面的两点其实已经足以对付昨天的面试题了,但是我们可以表现更优秀
复制代码

3.JSON.stringify扩展

JSON.stringify()其实可以接受三个参数,除了需要转化的js对象,还额外支持两个参数,
第一个用于参数的过滤,支持数组和对象。如果是数组,表示指定返回当前对象的属性,如果是函数表示对当前对象的所有属性(包括子对象的属性)需要进行过滤.(第二个参数建议自己尝试)
eg:
复制代码

image.png

image.png

4.JSON.parse()扩展

JSON.parse也可以接受一个额外参数进行扩展,将要进行转换为js对象的JSON格式进行过滤转换。
对上面的b对象加个birthday属性进行过滤eg:
复制代码

image.png

5.JSON.stringify不适用场景总结

1.遇见函数,undefined,对象(如symbol)会自动跳过.
2.如果单独对函数,symbol对象,undefined转换时会返回undefined
3.如果函数,symbol对象,undefined作为数组属性,根据返回undefined以null代替undefined原则,会返回null。
即let arr = [Symbol('foo'),undefined,function get(){}],JSON.stringify(arr); //[null,null,null]
4.转化值如果有toJSON函数,会返回toJSON函数的值。(这也是为什么不能转换Date格式的原因)
即JSON.stringify({id:1,name:2,toJSON:function(){return this.id}}) //"1"
5.如果对象中包含循环引用,会直接抛出错误。
复制代码
文章分类
前端
文章标签