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. Eclipse编辑Spring配置文件xml时自动提示类class包名

    第一步,先查看下自己的Eclipse是什么版本,步骤如下: 1.1 点击Eclipse菜单‘Help  -> About Eclipse’,如下图: 1.2 点击Eclipse图标如下,看清楚哦 ...

  2. Tomcat 配置访问限制:访问白名单和访问黑名单

    最近公司的阿里云服务器上配置的 Tomcat 服务器运行 java的环境,但是通过观察 Tomcat 这几天的日志发现,有很多莫名其妙的 IP 访问主机下莫名其妙的地址,如:/80./testprox ...

  3. C++中创建对象的时候加括号和不加括号的区别(转)

    c++创建对象的语法有----- 1 在栈上创建 MyClass a; 2 在堆上创建加括号 MyClass *a= new MyClass(); 3 不加括号 MyClass *a = new My ...

  4. mongoose 常用数据库操作 删除

    删除 Model.remove(conditions, [callback]) try.js var User = require("./user.js"); function d ...

  5. vue v-modle修饰符.number .trim

    语法糖: 在不影响功能的情况下,添加某种方法实现同样的效果,从而方便程序开发. .number:可以将输入转换成Number类型,否则虽然输入的是数字,但它的类型其实是String. .trim:自动 ...

  6. elasticsearch依赖的jackson-jar包与jboss依赖的jackson-jar包“版本”冲突

    elasticsearch依赖的jackson-jar包与jboss依赖的jackson-jar包“版本”冲突,导致elasticsearch相关功能在本地tomcat服务器正常,但是部署到jboss ...

  7. flexbox布局一

    flexbox布局是一种新的css布局,flex是flexible的简写,所以flexbox就可以理解为可伸缩布局.而可伸缩性也是flexbox布局的亮点,至于如何可伸缩,看完下面的介绍大家应该就会有 ...

  8. Java里的参数类型/返回值类型

    参数类型/返回值类型: ##数据类型: ###基本类型: ###引用类型: ####数组 ####类 ####接口 参数类型/返回值类型是类和接口的情况: 1.参数类型是普通类的情况 为什么写成静态, ...

  9. 管理员技术(一):装机预备技能、安装一台RHEL7虚拟机、使用RHEL7图形桌面、Linux命令行基本操作

    一.装机预备技能 问题: 本例要求安装一台可用的KVM服务器:      1> RHEL与CentOS系统有什么关联?      2> 第2块SCSI硬盘的第3个逻辑分区,Linux如何表 ...

  10. PHP中关于Phar的学习

    什么是phar 一个PHP程序往往是由多个文件组成的,如果能够集中为一个文件来分发和运行是很方便的.phar便应运而生.大概跟java的jar文件是差不多类似的.但是php的phar文件是可以由php ...