深拷贝不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深拷贝的方法递归复制到新对象上。

function deepClone(obj){let obj_ = JSON.stringify(obj),loneObj = JSON.parse(obj_);return loneObj
}
let a=[1,2,3,4,[2,3,4]],
b = deepClone(a);
console.log(a,b);

结果:

弊端:

1.如果 obj 里面有时间对象,则 JSON.stringify 后再 JSON.parse 的结果,时间将转为字符串的形式,而不是对象的形式

let obj = {a:123,b:[new Date(),new Date()]
}
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj,newObj);

例如:

2.如果 obj 里有 RegExp (正则表达式的缩写)、Error 对象,则序列化的结果将只得到空对象;

let obj = {a:123,b:/aabb[a-z]\d/,c:new TypeError('typeError')
}
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj,newObj);

3、如果 obj 里有函数(function),undefined,Symbol 则序列化的结果会把 function 或 undefined 丢失;

let obj = {a:123,fn:function(){let a = 123;console.log(a)},c:undefined,d:Symbol('foo')
}
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj,newObj);

4、如果obj里有 NaN、Infinity 和 -Infinity,则序列化的结果会变成 null

let obj = {a:123,b:NaN,c:Infinity,d:-Infinity
}
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj,newObj);

5、JSON.stringify() 只能序列化对象的可枚举的自有属性,例如如果 obj 中的对象是有构造函数生成的, 则使用 JSON.parse(JSON.stringify(obj)) 深拷贝后,会丢弃对象的 constructor;

class Student{constructor(){this.a = 1;this.b = 2;}
}
let obj = {a:123,b:new Student()
}
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj,newObj);

手动设置某属性不可枚举:

let obj = {a:123,b:234
}
Object.defineProperty(obj,'c',{value:22,enumerable:false,
})
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj,newObj);

6、如果对象中存在循环引用的情况也无法正确实现深拷贝;

当存在循环引用的时候,JSON.stringify 会一直去序列化所有对象,包括引用的对象,一直往复会爆栈,所以JSON.stringify 遇到循环引用会直接抛出异常,解决方法,利用一个 map 来存储对象(利用JSON.stringify的第二个参数)

let a = {aaa: 123}
let b = {bbb: 234}
a.child = b
b.parent = a// 声明cache变量,便于匹配是否有循环引用的情况
let cache = []
let res = JSON.stringify(a, function(key, value){if (typeof value === 'object' && value !== null) {if (cache.includes(value)) {// 移除return}// 收集所有对象cache.push(value)}return value
})
// 清空,便于垃圾回收机制回收
cache = nullconsole.log(res) //'{"aaa":123,"child":{"bbb":234}}'

总结:

  • Date 对象变为字符串
  • RegExp、Error 对象变为空对象 {}
  • 函数、undefined、Symbol 属性丢失
  • NaN、Infinity、-Infinity 变为 null
  • enumerable 为 false 的属性丢失
  • 循环引用的对象不能正确拷贝

用法简单,然而使用这种方法会有一些隐藏的坑:因为在序列化 JavaScript 对象时,所有函数和原型成员会被有意忽略。

通俗点说,JSON.parse(JSON.stringfy(X)),其中 X 只能是 Number, String, Boolean, Array,扁平对象,即那些能够被 JSON 直接表示的数据结构。

JSON.stringify() 常用方式

判断数组是否包含某对象,或者判断对象是否相等

是否相等:

let obj = {a:123,b:456,
}
let obj2 = {a:123,b:456,
}
console.log(JSON.stringify(obj) === JSON.stringify(obj2));//true

是否包含:

let arr = [{a:1,b:2},{a:2,b:3},{a:3,b:4}
]
let obj = {a:2,b:3}
console.log(JSON.stringify(arr).includes(JSON.stringify(obj)));//true

让 localStorage / sessionStorage 可以存储对象。

localStorage/sessionStorage 默认只能存储字符串,而实际开发中,我们往往需要存储的数据多为对象类型,那么这里我们就可以在存储时利用 Json.stringify() 将对象转为字符串,取出时利用 JSON.parse() 将字符串转为对象即可。

sessionStorage.setItem('user',JSON.stringify({name:'aaa',age:16}));
console.log(JSON.parse(sessionStorage.getItem('user')));//{name: "aaa", age: 16}

JSON.stringify()与toString()这两者虽然都可以将目标值转为字符串,但本质上还是有区别的

let arr = [12,12,12];
console.log(JSON.stringify(arr),arr.toString());
//[12,12,12] 12,12,12

利用 JSON.stringify 深拷贝的弊端相关推荐

  1. json.stringify()与json.parse()的区别,json.stringify()的妙用

    一.JSON.stringify()与JSON.parse()的区别 最近做项目,发现JSON.stringify()使用场景真的挺多,我们都知道JSON.stringify()的作用是将 JavaS ...

  2. JSON.stringify的作用

    是一个用于序列化对象的方法 接受三个参数:json.stringify(value,replacer,space) 第一个参数:value表示要被序列化的对象(接受对象或数组类型) 第二个参数:rep ...

  3. 使用JSON.parse(),JSON.stringify()实现对对象的深拷贝

    使用JSON.parse(),JSON.stringify()实现对对象的深拷贝 根据不包含引用对象的普通数组深拷贝得到启发,不拷贝引用对象,拷贝一个字符串会新辟一个新的存储地址,这样就切断了引用对象 ...

  4. 循环遍历多层json_面试官:JSON.stringify() 实现深拷贝有什么问题

    为什么要进行深拷贝 JS中的变量在内存中存储分为值类型和引用类型: 值类型: 1.占用空间固定,保存在栈中: 2.保存与复制的是值本身: 3.基本类型数据是值类型(String,Number,unde ...

  5. js深度复制一个对象使用JSON.stringify是最好的办法吗

    转载自   js深度复制一个对象使用JSON.stringify是最好的办法吗 深度复制一个对象,看到很多种方法,最简单的是: var newObject = JSON.parse(JSON.stri ...

  6. 带你一起实现 JSON.Stringify 方法

      JSON.Stringify方法能够站在全局考察对 JS 各种数据类型理解的深度,对各种极端的边界情况处理能力,以及JS的编码能力.之所以将这篇作为这一模块的进阶,是因为想把整个数据类型的知识点串 ...

  7. 第六讲:JSON.stringify 方法

    我在上一讲为你剖析了闭包这个难点,带你了解了作用域.闭包产生的原因及表现形式.那么这一讲,我们一起来手工实现一个JSON.stringify 的方法. 这个方法能够站在全局考察你对 JS 各种数据类型 ...

  8. JSON.stringify报cyclic object value错误

    这是一个典型的循环引用的错误,一个对象里引用自己就会立刻得到这个错误: obj = { x:555, y: "hi" }; obj.myself = obj;try{json = ...

  9. JSON.stringify()还可以这么用

    最近做项目的时候遇到一个对象深拷贝的问题,网上看了下发现最为简便的方法是JSON.stringify(),比如你要深拷贝一个对象,可以这么做: var test={a:"hello" ...

最新文章

  1. 索引原理,查询机制(转)
  2. win10如何换pip源
  3. Bootstrap的响应式,当文字超过div长度,换行问题的处理!
  4. how does UI Framework get url of detail page - _router
  5. Javascript阻止表单提交
  6. 【转载】移动端布局概念总结
  7. MQTT工作笔记0001---MQTT协议概述
  8. BCD与ASCII码互转-C语言实现
  9. 超多种类的报表模板,填上数据就能用,全拿走!
  10. 力扣 双周赛补题 2086. 从房屋收集雨水需要的最少水桶数
  11. 【RTOS】为H7配套的uCOS-III模板也是可以用于MDK AC6的,提供个模板
  12. SQL Server 数据库文件路径迁移步骤
  13. 基于MATLAB的数字水印技术实现解析
  14. 浅析HiShop、Shopex、ECshop、V5shop四大网店系统
  15. Right-BICEP 测试四则运算程序
  16. 【环境配置】gazebo搭建仿真机器人研究动态障碍物算法
  17. 复制mathtype到Word时
  18. ROS 几款IDE,一些小坑
  19. 万字带图教程带你从零开始安装CentOS
  20. 【电脑使用】介绍几种安装Windows系统的方法及一些个人理解

热门文章

  1. r语言nonzerocoef函数_R语言pec包深度验证Cox模型
  2. 固态继电器原理以及为什么输出分正负极性
  3. 【RTS】李宇翔 monibuca 讲座 学习
  4. lto1: fatal error: bytecode stream..generated with LTO version 6.2 instead of the expected 8.1 compi
  5. 【Assassin's Creed】v刺客信条 中文版V3.1.7 gameloft经典动作游戏
  6. DirectFB的接口详解 .
  7. 计算机工程师技术特长,工作能力及特长 怎么写?
  8. html5响应式布局案例
  9. 赚了!用Python写爬虫,月赚49K!
  10. Win7截图快捷键是什么?