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. STL_map

    map<string,int> m; int main() { m[; cout<<m["]<<endl; ; }

  2. element 点击切换按钮的颜色

    1.html <el-button-group label="时间"> <el-button @click="seeHour" :type=& ...

  3. 【JavaWeb项目】一个众筹网站的开发(八)后台页面详细设置

    一.user.jsp改造 删除引入菜单 抽取导航栏 nav-bar.jsp,删除引入导航栏 删除引入main.jsp的到好烂 数据库里添加url 报错,url不对 没有/ url正确 action=& ...

  4. Delphi Close、Halt、terminate、ExitProcess的区别

    Close:1.只关闭本窗体2.当Close是一个主窗体时,程序会退出.3.Close会发生FormClose事件,FormCloseQuery事件4.主窗体close以后程序就Application ...

  5. Comet Contest#11 F arewell(DAG计数+FWT子集卷积)

    传送门. 题解: 4月YY集训时做过DAG计数,和这个基本上是一样的,但是当时好像直接暴力子集卷积,不然我省选时不至于不会,这个就多了个边不选的概率和子集卷积. DAG计数是个套路来的,利用的是DAG ...

  6. 【LeetCode 19】删除链表的倒数第N个节点

    题目链接 [题解] 经典的一道题. 让p1指向链表的第一个元素. 让p2指向链表的第二个元素. 然后让他们俩同时往后移动. 直到p2到达链表的尾巴. 这时p1和p2之间总是隔了n-1个元素. 所以p1 ...

  7. Anaconda配置

    0x00 下载 为了更快的下载,可以到清华开源软件镜像站下载 地址:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 在此以Anaconda ...

  8. webpack 添加eslint代码审查

    1). 添加包 npm install eslint --save-dev npm install eslint-loader --save-dev npm install eslint-plugin ...

  9. noip2002 普及组 过河卒

    题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为"马拦过 ...

  10. Fiddler设置抓一个域名下个包

    设置抓一个域名下个包 右侧Filters 勾选Use Filters 勾选Hosts 选择 Show only the follwing Hosts  设置好自己的抓包的域名