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] }

最新文章

  1. [LeetCode] Closest Binary Search Tree Value 最近的二分搜索树的值
  2. topcoder SRM 618 DIV2 LongWordsDiv2
  3. 【leetcode❤python】 223. Rectangle Area
  4. JAVA 聊天窗口
  5. JSTL截取字符串
  6. C#JSON格式数据的转换
  7. 论山寨手机与Android 【11】移动网络规范的合纵连横
  8. MFC数据类型(data types)
  9. 使用Idea作为go的IDE
  10. sqlserver内存释放
  11. VMWare虚拟机启动报错物理内存不足
  12. linux 云计算Openstack搭建
  13. Ubuntu启动eclipse问题
  14. 用Shell编写的俄罗斯方块代码
  15. SpringBoot------Maven Clean报错
  16. BizDevOps — the true value proposition of workflow engines
  17. 如何将IOS版本的更新下载文件指向到自己的服务器
  18. hdu 5040 bfs
  19. leetcode 刷题
  20. oracle的常用函数 instr() 和substr()函数

热门文章

  1. css负边距之详解(子绝父相)
  2. mongoose 数据库连接
  3. webapp兼容问题解决
  4. 把sublime添加到右键快捷菜单
  5. jdk环境配置-windows 10
  6. (转)Linux C 多线程编程----互斥锁与条件变量
  7. elasticsearch5.5.2安装
  8. Tomcat运行错误示例二
  9. Fiddler设置抓一个域名下个包
  10. jquery中的ajax方法参数的用法和他的含义