JSON.parse(JSON.stringfy(obj))深复制的陷阱

一个例子

关于深复制很多在工作中都会遇到,之前觉得json这个东西很好用,如下

obj = {a: 1, b: {b: 2, c: {c: 3}}, origin: true, x: 1, xx: '1', xxx: null, xxxx: undefined, xxxxx: ()=> {}, xxxxxx: {}}
obj1 = function jsonCopy (obj) {
  return JSON.parse(JSON.stringify(obj))
}

得到的结果是:

JSON.parse(JSON.stringfy(obj))深复制的陷阱_第1张图片
test result

吓尿了!之前代码有坑啊!
JSON.stringfy

  • 查询一下MDN: JSON.stringfy

1 非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中。
布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。
2 undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。
3 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
4 所有以 symbol 为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。
5 不可枚举的属性会被忽略

  • 查询了一下json的定义

JSON 是一种语法,用来序列化对象、数组、数值、字符串、布尔值和 null 。它基于 JavaScript 语法

  • 维基百科中定义json

JSONJavaScript Object Notation,JavaScript对象表示法)是一种由道格拉斯·克罗克福特构想和设计、轻量级的数据交换语言,该语言以易于让人阅读的文字为基础,用来传输由属性值或者序列性的值组成的数据对象。尽管JSON是JavaScript的一个子集,但JSON是独立于语言的文本格式,并且采用了类似于C语言家族的一些习惯

首先json是用于数据交换的一种规范,我们可以用json格式的数据与后台进行数据交换,然后json支持的数据类型是:object, array ,number, string, boolean,null,没有undefined和function。用这个jsonCopy方法复制js定义赋值的对象有风险,但是你复制从后台取来的对象没有关系,因为中间的管道不支持。所以你得清楚的知道你在干什么。

更好的深复制

// 引vuex中深复制的实现

function find (list, f) {
  return list.filter(f)[0]
}
deepCopy (obj, cache = []) {
  // just return if obj is immutable value
  if (obj === null || typeof obj !== 'object') {
    return obj
  }

  // if obj is hit, it is in circular structure
// 防止循环引用
  const hit = find(cache, c => c.original === obj)
  if (hit) {
    return hit.copy
  }

  const copy = Array.isArray(obj) ? [] : {}
  // put the copy into cache at first
  // because we want to refer it in recursive deepCopy
  cache.push({
    original: obj,
    copy
  })

  Object.keys(obj).forEach(key => {
    copy[key] = deepCopy(obj[key], cache)
  })

  return copy
}

你可能感兴趣的:(JSON.parse(JSON.stringfy(obj))深复制的陷阱)