javascript浅拷贝深拷贝理解记录
javascript的深拷贝和浅拷贝问题几乎是面试必问的问题。好记性不如烂笔头,特此来记录一下自己对深拷贝浅拷贝的理解。
顾名思义,拷贝就是copy复制,在js中可以浅而理解为对一个对象或者数组的复制。但是复制后的对象或者数组是否是和原来的对象指向同一个地址内存还是新开辟了一个地址内存,这就衍生出了javascript的深拷贝和浅拷贝的问题了;深复制和浅复制只针对像 Object, Array 这样的复杂对象的。简单来说,浅复制只复制一层对象的属性,而深复制则递归复制了所有层级。
一、javascript浅拷贝
浅拷贝:只复制一层对象属性,可以理解为,只复制对象的基本属性类型,而基本属性类型是存放在栈内存中的,可以直接修改访问的,所以当浅拷贝时,拷贝的对象只是拷贝了原对象的属性,而值都是指向同一个栈内存中的数据,当对象属性值发生修改时,原对象也会被修改。如下示例:
let arr1 = {
color:'red',
name:'apple',
weight:'100g',
detail:{
big:'true',
eating:'no'
}
};
let arr2;
arr2 = arr1;
arr2.color = 'black';
console.log(arr2);
console.warn(arr1);
输出值:

可以看到,当arr2的color发生变化时,被复制的对象arr1的color值也发生了变化。
但是在实际项目应用中,我们复制了某个对象之后绝大多数情况下都是不希望被复制的对象的值会发生变化,这里就涉及到javascript的深拷贝问题以及他的实现。
二、javascript深拷贝
深拷贝:它不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上。这就不会存在上面 obj 和 shallowObj 的 arr 属性指向同一个对象的问题。这是我从某官网看来的解释,我感觉挺绕的,结合对象来看,深拷贝存在于对象这种引用类型中,而引用类型的数据是存在堆内存上的,变量保存的是一个指针,这个指针指向另一个位置。当需要访问引用类型(如对象,数组等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。深拷贝可以看做是在堆内存中新开辟了一个内存空间,复制后的对象的属性所指的指针会指向新开辟的内存空间的地址。所以复制后的对象对属性值进行修改不会影响原对象的属性值。
那如何实现深拷贝呢?
1、通过JSON.parse(JSON.stringify(arr))接上面的例子:
let arr3 = JSON.parse(JSON.stringify(arr1));
arr3.color="balck";
console.log(arr3);
console.warn(arr1);
输出结果:

这个方法我觉得是最简洁的,但是它有一些弊端:
a、对于正则表达式类型、函数类型等无法进行深拷贝(而且会直接丢失相应的值)
b、深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object
c、如果对象中存在循环引用的情况也无法正确处理。
2、通过for循环递归调用
function deepClone(obj){
//判断obj是否是数组
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
var arr4 = deepClone(arr1);
arr4.name='bananer';
console.log(arr4);
console.warn(arr1);
输出结果:

但是,这样的深拷贝进行的循环递归调用,如果对象数据量庞大显然会影响性能,所以一般在项目中很少使用,循环进行深拷贝,可以考虑其他方式来实现对象值的复制引用。
3、数组concat方法
let arr4 = [1,2,3]
let arr5 = [].concat(arr4)
arr5.push(4)
console.log(arr4, arr5, 'deep copy')
// [1,2,3] [1,2,3,4]
4、js扩展运算符(...)
let arr8 = [1,2,3]
let arr9 = [...arr8]
arr9.push(4)
console.log(arr8, arr9, 'deep copy 2')
// [1,2,3] [1,2,3,4]
javascript浅拷贝深拷贝理解记录的更多相关文章
- javascript浅拷贝深拷贝详解
一.浅拷贝 浅拷贝在现实中最常见的表现在赋值上面,例如 <!DOCTYPE html> <html lang="en"> <head> < ...
- 也来玩玩 javascript对象深拷贝,浅拷贝
经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One method of copying an object is ...
- javascript对象深拷贝,浅拷贝 ,支持数组
javascript对象深拷贝,浅拷贝 ,支持数组 经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One meth ...
- JavaScript之深拷贝&浅拷贝
深拷贝&浅拷贝,说起来都明白,但是说不出所以然.今天就系统的整理下思绪,一点点的将其分析出所以然 废话不多说 浅拷贝 简单的说就是一个值引用,学生时代接触过编程的人都应该了解过指针,浅拷贝可以 ...
- JavaScript的深拷贝和浅拷贝总结
深拷贝和浅拷贝 深拷贝:拷贝实例:浅拷贝:拷贝引用(原对象). 说深拷贝和浅拷贝之前,我先去了解了下高程书上的JavaScript的变量类型: 基本类型:undefined.null.Boolean. ...
- 【javascript】浅谈javaScript的深拷贝
前言: 最开始意识到深拷贝的重要性是在我使用redux的时候(react + redux), redux的机制要求在reducer中必须返回一个新的对象,而不能对原来的对象做改动,事实上,当时 ...
- $.extend()浅拷贝深拷贝
参考网址:http://bijian1013.iteye.com/blog/2255037 jQuery.extend() 函数用于将一个或多个对象的内容合并到目标对象. 注意:1. 如果只为$.ex ...
- 【javascript】详解javaScript的深拷贝
前言: 最开始意识到深拷贝的重要性是在我使用redux的时候(react + redux), redux的机制要求在reducer中必须返回一个新的对象,而不能对原来的对象做改动,事实上,当时 ...
- JavaScript实现深拷贝(深复制) 面试题
1.两种方法实现深拷贝(深复制) (1)方法一:兼容性好,请仔细看代码(网上大部分代码有Bug) (2)方法二:需要对象满足JSON数据格式.JOSN数据格式:http://www.cnblogs.c ...
随机推荐
- Geodetic集合
图G是一个无向连通图,没有自环,并且两点之间至多只有一条边.我们定义顶点v,u最短路径就是从v到u经过边最少的路径.所有包含在v-u的最短路径上的顶点被称为v-u的Geodetic顶点,这些顶点的集合 ...
- PS、AI、AE常用快捷键大全
PS,AI,AE最常用的快捷键来了. 注意:Mac用户请自觉把Ctrl换成Command理解就行. 2017 Adobe Photoshop CC 快捷键 2017Adobe Illustrator快 ...
- 学习bn算法
好处: 1.归一化后有什么好处呢?原因在于神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低: 2.另外一方面,一旦每批训练数据的分布各不相同(b ...
- JAVA对字符串的压缩与解压缩
import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException; ...
- sql server 2008安装的时候选NT AUTHORITY\NEWORK SERVICE 还是选 NT AUTHORITY\SYSTEM ?
sql server 2008安装的时候选NT AUTHORITY\NEWORK SERVICE 还是选 NT AUTHORITY\SYSTEM ? sql server 2008安装的时候选NT A ...
- 2018.09.05 bzoj1010: [HNOI2008]玩具装箱toy(斜率优化dp)
传送门 一道经典的斜率优化dp. 推式子ing... 令f[i]表示装前i个玩具的最优代价. 然后用老套路. 我们只考虑把第j+1" role="presentation" ...
- Unit Testing of Spring MVC Controllers1
我们的pom.xml文件相关的部分看起来如下: <dependency> <groupId>com.fasterxml.jackson.core</groupId& ...
- cmd运行命令
winver检查Windows版本 dxdiag检查DirectX信息 mem.exe显示内存使用情况 Sndvol32音量控制程序 sfc.exe系统文件检查器 gpedit.msc 组策略 reg ...
- 一)如何开始 ehcache ?
官网地址 http://www.ehcache.org/ 从哪开始 第一步优先下载 http://www.ehcache.org/downloads/ 下载 Ehcache 2.10.0 .tar.g ...
- faceswap使用手冊
cd faceswap cd faceswap-master python faceswap.py gui Notice: This repository is not operated or mai ...