使用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))实现深拷贝的局限及扩展的更多相关文章

  1. javascript 数组和对象的浅复制和深度复制 assign/slice/concat/JSON.parse(JSON.stringify())

    javascript 数组和对象的浅度复制和深度复制在平常我们用 ‘=’来用一个变量引用一个数组或对象,这里是‘引用’而不是复制下面我们看一个例子引用和复制是什么概念 var arr=[1,2,3,' ...

  2. JSON.parse(JSON.stringify()) 实现对对象的深拷贝

    JSON.parse(JSON.stringify(obj))我们一般用来深拷贝,其过程说白了 就是利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反 ...

  3. 关于JSON.parse(JSON.stringify(obj))实现深拷贝应该注意的坑

    JSON.parse(JSON.stringify(obj))我们一般用来深拷贝,其过程说白了 就是利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反 ...

  4. 实现深拷贝还在用JSON.parse(JSON.stringify(obj))?带你用JS实现一个完整版深拷贝函数

    使用JavaScript实现深拷贝 1.JSON序列化实现深拷贝 在JS中,想要对某一个对象(引用类型)进行一次简单的深拷贝,可以使用JSON提供给我们的两个方法. JSON.stringfy():可 ...

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

    根据不包含引用对象的普通数组深拷贝得到启发,不拷贝引用对象,拷贝一个字符串会新辟一个新的存储地址,这样就切断了引用对象的指针联系. 测试例子: var test={ a:"ss", ...

  6. JSON.parse(JSON.stringify(obj))

    JSON.parse(JSON.stringify(obj)实现数组的深拷贝 利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象

  7. JSON.parse JSON.stringify

    JSON.stringify() undefined 值.函数或者XML值会被忽略 数组当中含有 undefined值,函数或XML值,该数组中的这些值将会被当成 null 正则对象会被转成空对象 J ...

  8. 【Immutable】拷贝与JSON.parse(JSON.stringify()),深度比较相等与underscore.isEqual(),性能比较

    样本:1MB的JSON文件,引入后生成500份的一个数组: 结果如下: 拷贝性能: JSON.parse(JSON.stringify()) 的方法:2523.55517578125ms immuta ...

  9. this.treeData = JSON.parse(JSON.stringify(this.d)) 树的序列化反序列化

    this.treeData = JSON.parse(JSON.stringify(this.d))

  10. JSON.parse(JSON.stringify()) 实现对对象的深度拷贝,从而互不影响

    JSON.parse(JSON.stringify({"key": "value"})) 根据不包含引用对象的普通数组深拷贝得到启发,不拷贝引用对象,拷贝一个字 ...

随机推荐

  1. pyspark集成访问hive数据踩坑记录

    当前环境anaconda3.python3.9.13.jupyter 需要安装的pyspark.py4j pyspark和py4j的离线安装包地址Links for pyspark (tsinghua ...

  2. 2. C++的编译/链接模型

    C++的编译/链接模型 简单的加工模型 问题:无法处理大型程序 加工耗时较长 即使少量修改,也需要重新加工 解决方案:分块处理 好处 编译消耗资源,但一次处理输入较少 链接程序较多,但处理速度较快 便 ...

  3. 10.2 web服务器

    Web客户端和服务器之间的交互用的是一个基于文本的应用级协议,叫做HTTP(Hypertext Transfer Protocol,超文本传输协议).HTTP是一个简单的协议.一个Web客户端(即浏览 ...

  4. 论如何直接用EF Core实现创建更新时间、用户审计,自动化乐观并发、软删除和树形查询(上)

    前言 数据库并发,数据审计和软删除一直是数据持久化方面的经典问题.早些时候,这些工作需要手写复杂的SQL或者通过存储过程和触发器实现.手写复杂SQL对软件可维护性构成了相当大的挑战,随着SQL字数的变 ...

  5. SQL Server AdventureWorks示例数据库

    SQL Server AdventureWorks2008R2 数据字典 AdventureWorks2008R2示例数据库下载 AdventureWorks2008R2数据字典(官网) Addres ...

  6. Pytest Pytest源码分析

    Pytest源码分析 By:授客 QQ:1033553122 测试环境 pytest 5.4.3 测试脚本mytest.py #!/usr/bin/env python # -*- coding:ut ...

  7. Vue export & export default & import 总结

    Vue export & export default & import 总结 by:授客 QQ:1033553122 1.   实践环境 Vue 2.9.6 2.   简介 在ES6 ...

  8. 文件系统(十):一文看懂 UBI 文件系统

    liwen01 2024.07.21 前言 UBI (Unsorted Block Images)文件系统是一种用于裸 flash 的文件系统管理层.它是专为管理原始闪存设备而设计,特别适用于嵌入式系 ...

  9. 面试题-python 什么是闭包(closure)?

    前言 前面学了装饰器,那么闭包和装饰器有什么区别呢?闭包传递的是变量,而装饰器传递的是函数对象,只是传的参数内容不一样,闭包的概念包含了装饰器,可以说装饰器是闭包的一种,它只是传递函数对象的闭包. 先 ...

  10. Diffutoon下载介绍:真人视频转动漫工具,轻松获得上千点赞

    最近在刷短视频的时候,偶尔能看到一些真人转动漫风的作品,看起来给人一种新鲜感,流量都还不错,简简单单跳个舞,就能获得上千个点赞~ 那么,这种视频是怎么制作的? 本期给大家介绍一款AI转绘工具Diffu ...