JavaScript 中深拷贝实现
 
拷贝时候涉及到:
1、循环结构
2、判断数组 Array 还是对象 Object
 
函数实现
/**
* 获取满足条件的数组中的第一个元素
* @param {Array} list 将要筛选的数组
* @param {Function} f 用来过滤的函数
*/
function find(list, f) {
return list.filter(f)[0]
}
/**
* 深拷贝对象,同时考虑到了循环引用的情况
* 缓存了所有的嵌套对象和它的拷贝
* 如果检测到循环引用,返回拷贝,防止了无限循环
* @param {Object} obj 需要拷贝的对象
* @param {Array} cache 用来判断是否循环引用,存储对象以及对象的拷贝
*/
function deepCopy(obj, cache = []) {
// 为空或者不是对象则返回原 obj
if (obj === null || typeof obj !== 'object') {
return obj
} // 若是循环结构,则返回之前对象的 copy,而不是引用
const hit = find(cache, c => c.original === obj)
if (hit) {
return hit.copy
} const copy = Array.isArray(obj) ? [] : {}
// 将 copy 放入 cache 中
// 我们可能在递归中引用 copy
cache.push({
original: obj,
copy
}) Object.keys(obj).forEach(key => {
copy[key] = deepCopy(obj[key], cache)
}) return copy
}

应用

1、非嵌套例子:
const original = {
a: 1,
b: 'string',
c: true,
d: null,
e: undefined
}
const copy = deepCopy(original)
console.log('copy === original :', copy === original)
// copy === original : false
console.log('copy :', JSON.stringify(copy, null, 2))
// copy : {
// "a": 1,
// "b": "string",
// "c": true,
// "d": null
// }

2、嵌套例子:

const original = {
a: {
b: 1,
c: [
2,
3,
{
d: 4
}
]
}
}
const copy = deepCopy(original)
console.log('copy === original :', copy === original)
// copy === original : false
console.log('copy :', JSON.stringify(copy, null, 2))
// copy : {
// "a": {
// "b": 1,
// "c": [
// 2,
// 3,
// {
// "d": 4
// }
// ]
// }
// }
 
3、循环引用
const original = {
a: 1
}
original.circularExample = original const copy = deepCopy(original)
console.log('copy === original :', copy === original)
// copy === original : false
console.log('copy :', copy)
// 这里循环引用不可使用 JSON.stringify 来转换,会报错
// copy : { a: 1, circularExample: [Circular] }

JavaScript中深拷贝实现的更多相关文章

  1. Javascript中的深拷贝和浅拷贝

    var obj = { a:1, arr: [1,2] }; var obj1 = obj; //浅复制 var obj2 = deepCopy(obj); //深复制 javascript中创建对象 ...

  2. Javascript中的浅拷贝和深拷贝

    很多开发语言中都有浅拷贝和深拷贝的说法,这里简单区分一下它们在Javascript中的区别,以及jQuery中深拷贝的实现. 在谈浅拷贝和深拷贝之前,先要屡清楚Javascript中的按值访问和按引用 ...

  3. (译文)JavaScript基础——JavaScript中的深拷贝

    在JavaScript中如何拷贝一个对象? 通过引用调用 function mutate(obj) { obj.a = true; } const obj = {a: false}; mutate(o ...

  4. javascript中的深拷贝与浅拷贝

    javascript中的深拷贝与浅拷贝 基础概念 在了解深拷贝与浅拷贝的时候需要先了解一些基础知识 核心知识点之 堆与栈 栈(stack)为自动分配的内存空间,它由系统自动释放: 堆(heap)则是动 ...

  5. 深入理解JavaScript中的堆与栈 、浅拷贝与深拷贝

    JavaScript中的浅拷贝与深拷贝  学了这么长时间的JavaScript想必大家对浅拷贝和深拷贝还不太熟悉吧,今天在项目中既然用到了,早晚也要理清一下思路了,在了解之前,我们还是先从JavaSc ...

  6. javascript中的堆栈、深拷贝和浅拷贝、闭包

    堆栈 在javascript中,堆内存是用来存放引用类型的空间环境 而栈内存,是存储基本类型和指定代码的环境 在对象中的属性名具有唯一性,数字属性名=字符串属性名,但是在测试的时候你会发现,好像所有属 ...

  7. JavaScript中的深拷贝和浅拷贝!【有错误】还未修改!请逛其他园子!

    JavaScript中的深拷贝和浅拷贝! 浅拷贝 1.浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用.{也就是拷贝的是地址!简而言之就是在新的对象中修改深层次的值也会影响原来的对象!} // 2.深 ...

  8. JavaScript 中的数据类型

    Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...

  9. javascript 中继承实现方式归纳

    转载自:http://sentsin.com/web/1109.html 不同于基于类的编程语言,如 C++ 和 Java,javascript 中的继承方式是基于原型的.同时由于 javascrip ...

随机推荐

  1. 安装配置oh-my-zsh

    1.下载安装iterm:https://www.iterm2.com/ 2.安装zsh 查看系统当前使用的shell $ echo $SHELL /bin/bash 查看系统是否安装了zsh $ ca ...

  2. Packet for query is too large (1986748 > 1048576). You can change this value on the server by 异常

    场景:mybatis动态拼接,批量添加数据,因为数据太多,凭借过多,导致MySql数据库中插入大于1m的数据时,提示该异常. 解决办法:修改mysql的属性 max_allowed_packet即可. ...

  3. Map集合类(二.其他map集合jdk1.8)

    java集合笔记一 java集合笔记二 java集合笔记三 1.hashtable(线程安全) 1.存储数据为数组+链表2.存储键值对或获取时通过hash值取模数组长度确定节点在数组中的下标位置 in ...

  4. vue中使用axios进行http通信

    1.安装 npm install axios 2.在main.js中全局注册 // axios不可以通过use引入,可以通过修改vue原型链 import axios from 'axios' Vue ...

  5. springboot输出hello world,3种方式(String,JSON,jsp),IDEA开发工具

    新建项目: File -> new -> Project -> Spring Initializr -> Next -> Next -> Next-> Pro ...

  6. vue 实现分页

    1 新建 pager.js 文件 /** * [pagination 分页组件] * @param {Number} total [数据总条数] * @param {Number} display [ ...

  7. Shiro学习(14)SSL

    对于SSL的支持,Shiro只是判断当前url是否需要SSL登录,如果需要自动重定向到https进行访问. 首先生成数字证书,生成证书到D:\localhost.keystore 使用JDK的keyt ...

  8. 「题解」:$Smooth$

    问题 A: Smooth 时间限制: 1 Sec  内存限制: 512 MB 题面 题面谢绝公开. 题解 维护一个队列,开15个指针,对应前15个素数. 对于每一次添加数字,暴扫15个指针,将指针对应 ...

  9. (转)阿里RocketMQ Quick Start

    转:http://blog.csdn.net/a19881029/article/details/34446629 RocketMQ单机支持1万以上的持久化队列,前提是足够的内存.硬盘空间,过期数据数 ...

  10. Python 中练习题涉及到的无穷大和无穷小问题。

    首先来看一下所见的python联系题. inf = infinite 无限制的 float("inf")-1执行后的结果是:() A 1 B inf C -inf D 0 该考点考 ...