小tips:使用JSON.parse(JSON.stringify(object))实现深拷贝的局限及扩展
使用JSON.parse(JSON.stringify(object))实现深拷贝局限
大部分情况我们都可以使用JSON.parse(JSON.stringify(object))来实现深拷贝,但该方法也有局限性,如下:
- 会忽略
undefined - 会忽略
symbol - 不能序列化函数
- 不能解决循环引用的对象
例如:
let a = {
age: undefined,
sex: Symbol('male'),
jobs: function() {},
name: 'yck'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "yck"}
借用 MessageChannel 实现深拷贝
MessageChannel API允许我们创建一个新的消息通道,并通过它的两个MessagePort属性发送数据。
var channel = new MessageChannel();
这样就创建了一个管道。
实例属性:
channel.port1
channel.port2
获取实例的两个端口,注意的是,两个端口都是只读的。
简单来说,MessageChannel创建了一个通信的管道,这个管道有两个端口,每个端口都可以通过postMessage发送数据,而一个端口只要绑定了onmessage回调方法,就可以接收从另一个端口传过来的数据。
一个简单的例子:
var channel = new MessageChannel();
var port1 = channel.port1;
var port2 = channel.port2;
port1.onmessage = function(event) {
console.log("port1收到来自port2的数据:" + event.data);
}
port2.onmessage = function(event) {
console.log("port2收到来自port1的数据:" + event.data);
} port1.postMessage("发送给port2");
port2.postMessage("发送给port1");
而通过 postMessage() 方法传输的 message 参数是深拷贝的。
function deepClone(val) {
return new Promise((resolve,reject) => {
const {port1,port2} = new MessageChannel();
port2.onmessage = e => resolve(e.data);
port1.postMessage(val);
})
}
let obj = {
age: undefined,
name: 'yck',
c: {
d: true
}
}
obj.c.e = obj.c; // 循环引用
// 注意该方法是异步
async function test() {
const clone = await deepClone(obj);
console.log(clone) // {age: undefined, name: "yck", c: {…}}
}
test()
但这个深拷贝只能解决 undefined 和循环引用对象的问题,对于 Symbol 和 function 依然束手无策。
详细可参考:《MessageChannel 消息通道》
简易版的深拷贝
var extendCopy = (function f(p,c){
var c = c || {};
for (var i in p) {
if(typeof p[i] === 'object'){
c[i] = (p[i] instanceof Array) ? [] : {};
f(p[i],c[i]);
}else{
c[i] = p[i];
}
}
return c;
});
详细可参考:《小tips:JS之浅拷贝与深拷贝》
lodash 的深拷贝函数
语法:
_.cloneDeep(value)
示例:
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false
地址:https://lodash.com/docs/4.17.15#cloneDeep
小tips:使用JSON.parse(JSON.stringify(object))实现深拷贝的局限及扩展的更多相关文章
- javascript 数组和对象的浅复制和深度复制 assign/slice/concat/JSON.parse(JSON.stringify())
javascript 数组和对象的浅度复制和深度复制在平常我们用 ‘=’来用一个变量引用一个数组或对象,这里是‘引用’而不是复制下面我们看一个例子引用和复制是什么概念 var arr=[1,2,3,' ...
- JSON.parse(JSON.stringify()) 实现对对象的深拷贝
JSON.parse(JSON.stringify(obj))我们一般用来深拷贝,其过程说白了 就是利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反 ...
- 关于JSON.parse(JSON.stringify(obj))实现深拷贝应该注意的坑
JSON.parse(JSON.stringify(obj))我们一般用来深拷贝,其过程说白了 就是利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反 ...
- 实现深拷贝还在用JSON.parse(JSON.stringify(obj))?带你用JS实现一个完整版深拷贝函数
使用JavaScript实现深拷贝 1.JSON序列化实现深拷贝 在JS中,想要对某一个对象(引用类型)进行一次简单的深拷贝,可以使用JSON提供给我们的两个方法. JSON.stringfy():可 ...
- 使用JSON.parse(),JSON.stringify()实现对对象的深拷贝
根据不包含引用对象的普通数组深拷贝得到启发,不拷贝引用对象,拷贝一个字符串会新辟一个新的存储地址,这样就切断了引用对象的指针联系. 测试例子: var test={ a:"ss", ...
- JSON.parse(JSON.stringify(obj))
JSON.parse(JSON.stringify(obj)实现数组的深拷贝 利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象
- JSON.parse JSON.stringify
JSON.stringify() undefined 值.函数或者XML值会被忽略 数组当中含有 undefined值,函数或XML值,该数组中的这些值将会被当成 null 正则对象会被转成空对象 J ...
- 【Immutable】拷贝与JSON.parse(JSON.stringify()),深度比较相等与underscore.isEqual(),性能比较
样本:1MB的JSON文件,引入后生成500份的一个数组: 结果如下: 拷贝性能: JSON.parse(JSON.stringify()) 的方法:2523.55517578125ms immuta ...
- this.treeData = JSON.parse(JSON.stringify(this.d)) 树的序列化反序列化
this.treeData = JSON.parse(JSON.stringify(this.d))
- JSON.parse(JSON.stringify()) 实现对对象的深度拷贝,从而互不影响
JSON.parse(JSON.stringify({"key": "value"})) 根据不包含引用对象的普通数组深拷贝得到启发,不拷贝引用对象,拷贝一个字 ...
随机推荐
- 要想业务中台建得快,最好用Service Mesh来带
中国企业数字化转型进入深水区,业务中台及下一代微服务Service Mesh(服务网格)被越来越多的人关注,本文结合网易轻舟微服务Service Mesh实践,解析业务中台为什么需要Service M ...
- vue 理解yarn start 和yarn dev的区别
yarn dev,当文件变动后,会自动重启. yanr start不会自动重启 nodemon会监听文件变动,跟yarn dev和yarn start无关.
- __int128的输入输出(快读快输)
引言:__int128不能用\(cin\)\(cout\)或\(scanf\)\(printf\). 快读 思想:把每一个字符读入,组成数字. int read(){ int x = 0,y = 1; ...
- 关于UE5打包DLC
首先打开Project Lanucher,参考下图:,其次编辑配置两个edit Profile,参考下图: 第一个用来打包项目,第二个生成DLC,dlc填写的名字和插件一样,Main的配置如下: DL ...
- 【Mybatis】02 快速入门Part2 补完CRUD
这是我们的UserMapper.xml文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...
- 【Java】【常用类】String
String表示字符串,Java所有的字符串字面值都是String类的实例实现 String是一个final修饰的类,代表不可变的字符序列 字符串是常量,用双引号表示,值在创建之后不能更改 Strin ...
- 使用 addRouteMiddleware 动态添加中间
title: 使用 addRouteMiddleware 动态添加中间 date: 2024/8/4 updated: 2024/8/4 author: cmdragon excerpt: 摘要:文章 ...
- 从论文到图谱,或许只差一个html
书接上回,在文章<论文图谱当如是:Awesome-Graphs用200篇图系统论文打个样>中,我向大家讲述了如何用图的方式思考图计算系统的演进历史,并在后续的系列文中结合Awesome-G ...
- VisionOn:新一代在线制图工具,简单易用又高颜值
Vision On 一款集流程图.思维导图.白板于一体的轻量级在线图形工具 在工作和学习过程中,通过可视化的图形,有助于清晰高效地表达我们的灵感.想法.思想. 工欲善其事,必先利其器. 目前,思维导图 ...
- Camera | 12.瑞芯微摄像头自动焦距马达驱动移植
本为你主要讲解如何让摄像头ov13850支持自动对焦功能. 摄像头的对角主要通过VCM马达驱动芯片DW9714来实现的. 一.环境 soc : rk3568 board: EVB1-DDR4-V10 ...