网站首页 > 精选教程 正文
深拷贝和浅拷贝的区别
1.浅拷贝: 将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用。
2.深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”。
为什么要使用深拷贝?
我们希望在改变新的数组(对象)的时候,不改变原数组(对象)
深拷贝的要求程度
我们在使用深拷贝的时候,一定要弄清楚我们对深拷贝的要求程度:是仅“深”拷贝第一层级的对象属性或数组元素,还是递归拷贝所有层级的对象属性和数组元素?
怎么检验深拷贝成功
改变任意一个新对象/数组中的属性/元素, 都不改变原对象/数组
一、只对第一层级做拷贝
深拷贝数组(只拷贝第一级数组元素)
1.直接遍历
var array = [1, 2, 3, 4];
function copy (array) {
let newArray = []
for(let item of array) {
newArray.push(item);
}
return newArray;
}
var copyArray = copy(array);
copyArray[0] = 100;
console.log(array); // [1, 2, 3, 4]
console.log(copyArray); // [100, 2, 3, 4]
2. slice()
var array = [1, 2, 3, 4];
var copyArray = array.slice();
copyArray[0] = 100;
console.log(array); // [1, 2, 3, 4]
console.log(copyArray); // [100, 2, 3, 4]
slice() 方法返回一个从已有的数组中截取一部分元素片段组成的新数组(不改变原来的数组!)
用法:array.slice(start,end) start表示是起始元素的下标, end表示的是终止元素的下标
当slice()不带任何参数的时候,默认返回一个长度和原数组相同的新数组
3. concat()
var array = [1, 2, 3, 4];
var copyArray = array.concat();
copyArray[0] = 100;
console.log(array); // [1, 2, 3, 4]
console.log(copyArray); // [100, 2, 3, 4]
concat() 方法用于连接两个或多个数组。( 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。)
用法:array.concat(array1,array2,…,arrayN)
因为我们上面调用concat的时候没有带上参数,所以var copyArray = array.concat();实际上相当于var copyArray = array.concat([]);
也即把返回数组和一个空数组合并后返回
但是,事情当然不会这么简单,我上面的标题是 “深拷贝数组(只拷贝第一级数组元素)”,这里说的意思是对于一级数组元素是基本类型变量(如number,String,boolean)的简单数组, 上面这三种拷贝方式都能成功,但对第一级数组元素是对象或者数组等引用类型变量的数组,上面的三种方式都将失效,例如:
var array = [
{ number: 1 },
{ number: 2 },
{ number: 3 }
];
var copyArray = array.slice();
copyArray[0].number = 100;
console.log(array); // [{number: 100}, { number: 2 }, { number: 3 }]
console.log(copyArray); // [{number: 100}, { number: 2 }, { number: 3 }]
深拷贝对象
1.直接遍历
2.ES6的Object.assign
var obj = {
name: '八重嘤',
job: '逆神巫女'
}
var copyObj = Object.assign({}, obj);
copyObj.name = '樱花~~散!';
console.log(obj); // {name: "八重嘤", job: "逆神巫女"}
console.log(copyObj); // {name: "樱花~~散!", job: "逆神巫女"}附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wyp1725726792/java/article/details/102756183
3.ES6扩展运算符:
扩展运算符(…)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中,但是对多层嵌套对象,很遗憾,上面三种方法,都会失败:
var obj = {
name: {
firstName: '雷电',
lastName: '芽衣'
},
job: '学生'
}
var copyObj = Object.assign({}, obj)
copyObj.name.lastName = '雷电女王的鬼铠';
console.log(obj.name.lastName); // 雷电女王的鬼铠
console.log(copyObj.name.lastName); // 雷电女王的鬼铠
二、拷贝所有层级
有没有更强大一些的解决方案呢?使得我们能够
1.不仅拷贝第一层级,还能够拷贝数组或对象所有层级的各项值
2. 不是单独针对数组或对象,而是能够通用于数组,对象和其他复杂的JSON形式的对象
请看下面:
下面这一招可谓是“一招鲜,吃遍天”
1.JSON.parse(JSON.stringify(XXXX))
var array = [
{ number: 1 },
{ number: 2 },
{ number: 3 }
];
var copyArray = JSON.parse(JSON.stringify(array))
copyArray[0].number = 100;
console.log(array); // [{number: 1}, { number: 2 }, { number: 3 }]
console.log(copyArray); // [{number: 100}, { number: 2 }, { number: 3 }]
简单粗暴!!!好用不?嗯?你说啥? 你说上面的那种方法太无脑, 一定要自己写一段递归才有做技术的感觉? OK成全你!
2.手动写递归
var array = [
{ number: 1 },
{ number: 2 },
{ number: 3 }
];
function copy (obj) {
var newobj = obj.constructor === Array ? [] : {};
if(typeof obj !== 'object'){
return;
}
for(var i in obj){
newobj[i] = typeof obj[i] === 'object' ?
copy(obj[i]) : obj[i];
}
return newobj
}
var copyArray = copy(array)
copyArray[0].number = 100;
console.log(array); // [{number: 1}, { number: 2 }, { number: 3 }]
console.log(copyArray); // [{number: 100}, { number: 2 }, { number: 3 }]
【注意】:上文的所有的示例都忽略了一些特殊的情况: 对对象/数组中的Function,正则表达式等特殊类型的拷贝
三、存在大量深拷贝需求的代码——immutable提供的解决方案
实际上,即使我们知道了如何在各种情况下进行深拷贝,我们也仍然面临一些问题: 深拷贝实际上是很消耗性能的。(我们可能只是希望改变新数组里的其中一个元素的时候不影响原数组,但却被迫要把整个原数组都拷贝一遍,这不是一种浪费吗?)所以,当你的项目里有大量深拷贝需求的时候,性能就可能形成了一个制约的瓶颈了。
immutable的作用:
通过immutable引入的一套API,实现:
1.在改变新的数组(对象)的时候,不改变原数组(对象)
2.在大量深拷贝操作中显著地减少性能消耗
先睹为快:
const { Map } = require('immutable')
const map1 = Map({ a: 1, b: 2, c: 3 })
const map2 = map1.set('b', 50)
map1.get('b') // 2
map2.get('b') // 50
参考资料:
1.知乎《 javascript中的深拷贝和浅拷贝?》 https://www.zhihu.com/question/23031215
2.阮一峰 《ECMASript6入门》 http://es6.ruanyifeng.com/
3.MDN javascript 数组API https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
- 上一篇: Java:深拷贝与浅拷贝(Cloneable接口)
- 下一篇: 面试题:什么是浅拷贝和深拷贝?
猜你喜欢
- 2025-01-08 JVM(Java虚拟机)从0到1全部合集,强烈建议收藏
- 2025-01-08 你见过哪些实用到爆的 Java 代码技巧?
- 2025-01-08 2019最全的Java架构师面试120题解析(MySQL/Redis/架构/高并发等)
- 2025-01-08 Python元组与字典用法详解
- 2025-01-08 金蝶一面:Java基本数据类型有哪些?包装类型的常量池技术了解么
- 2025-01-08 阿里云Java实习岗面试记录整理(附答案详解)
- 2025-01-08 Java基础八股文背诵版
- 2025-01-08 Fury:一个基于JIT动态编译的高性能多语言原生序列化框架
- 2025-01-08 全网首发!马士兵内部共享—1658页《Java面试突击核心讲》
- 2025-01-08 百度文库不用会员也可复制文字
你 发表评论:
欢迎- 最近发表
-
- 我的世界光影MOD下载(我的世界光影mod下载安装)
- 我的世界1.7/1.8VoxelMap小地图MOD下载
- 我的世界1.7.10多世界 整合包(我的世界1.7.10forge整合包)
- 我的世界1.8最好用的修改器下载(我的世界1.8最好用的修改器下载安装)
- 我的世界更多弯曲动作MOD下载(我的世界更多弯曲动作mod下载手机版)
- 我的世界龙珠MOD下载(我的世界龙珠模组整合包下载)
- 我的世界1.7.10以太2 下载(我的世界以太2mod1.12.2)
- 我的世界虚拟人生MOD下载分享(我的世界虚拟人生下载安装)
- 我的世界无正版账号的简单联机方法(非网易版,仅适用于局域网)
- “我的语言极限,即是我的世界的极限。” ——《On Java》书籍推荐
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)