小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"})) 根据不包含引用对象的普通数组深拷贝得到启发,不拷贝引用对象,拷贝一个字 ...
随机推荐
- JavaScript系列:JS实现复制粘贴文字以及图片
目录 一. 基于 Clipboard API 复制文字(推荐) 基本概念 主要方法 使用限制 实际应用示例 二.基于 document.execCommand('copy') 缺陷 实际应用示例 说明 ...
- UE Spline 样条网格体组件添加碰撞
最近做的一个功能是通过Spline 生成管道模型. 如下图所示: 遇到的一个问题是需要给生成的管路加上碰撞.其中需要两个重要的步骤: 设置SplineMeshComponent的碰撞预设 找到&quo ...
- vue 理解yarn start 和yarn dev的区别
yarn dev,当文件变动后,会自动重启. yanr start不会自动重启 nodemon会监听文件变动,跟yarn dev和yarn start无关.
- oeasy教您玩转linux010206toilet
我们来回顾一下 上一部分我们都讲了什么? 用apt查询并下载了figlet 玩了一下字符画 设置了字符画的字体 但是没有修改颜色 这次我们来找找另一个命令toilet apt search toile ...
- TIER 0: Meow
TIER 0: Meow Virtual Machine 虚拟机 (VM) 指通过软件模拟完整计算机系统 可以实现环境隔离 模型宿主机不具备的架构 虚拟机的工作原理:在物理机器的操作系统上,以一个应用 ...
- 顺序表_C
// Code file created by C Code Develop #include "ccd.h" #include "stdio.h" #incl ...
- windows terminal 添加git bash
打开windows terminal点击设置 修改文件 找到profiles-->list添加一个节点 { "commandline": "C:\\Program ...
- 【Vue】自己编写排名组件
一.需求分析 这里我是用Echarts的柱状图,倒置下y轴x轴就实现了,然后产品说跟UI不一致 我一看UI这种又给我整不会了,然后想拿Echarts改改参数搞定,同事和群友都是说自己做,不要用Echa ...
- 【Docker】02 上手入门
环境前提: 软硬件设备:真机 | 服务器 | 虚拟机 操作系统:Linux 协议传输工具:XSHELL等等,直接操作就不用了 网路:必须得有 Docker的安装: 还好在学Linux的时候装了一下,发 ...
- 很好用的python游戏环境(续2):强化学习算法走迷宫游戏环境(导航问题 navigation):分享一个python语言的迷宫游戏环境
相关前文: 很好用的python游戏环境(续):强化学习算法走迷宫游戏环境(导航问题 navigation):分享一个python语言的迷宫游戏环境 项目的GitHub地址: https://gith ...