总结JavaScript对象的深浅拷贝
对象的浅拷贝与深拷贝
什么是对象的拷贝?
将一个对象赋值给另外一个对象, 我们称之为对象的拷贝什么是深拷贝, 什么是浅拷贝?
我们假设将A对象赋值给B对象浅拷贝是指, 修改B对象的属性和方法会影响到A对象的属性和方法, 我们称之为浅拷贝
以下几种情况都属于浅拷贝:
1、默认情况下对象之间的直接赋值都是浅拷贝
let A = {
name: 'zyx',
age: 20
}
let B = A
console.log(B) // {name: "zyx", age: 20}
//修改B的 name 属性
B.name = 'ls'
//A 也收到影响
console.log(A) // {name: "ls", age: 20}
console.log(B) // {name: "ls", age: 20}
赋值操作(包括对象作为参数、返回值),不会开辟新的内存空间,他只是赋值了对象的引用.也就是除了B这个名字之外,没有其他的内存开销,修改了A也就影响了B,修改了B,也就影响了A.
如图所示:

2、如果对象的属性包含了引用数据类型(数组、对象),那么哪怕不是直接赋值操作,而是开辟了一层新的内存空间,也就是说只拷贝了A对象的一层,这仍然属于浅拷贝。
let A = {
name: 'ls',
age: 20,
hobbies: ['dance','basketball','read'],
dogs:{
name: '大黄',
color: 'yellow'
}
}
let B = {}
//定义一个函数,把A对象的属性复制一份给B
function extend(obj1,obj2){
for(var key in obj1){
obj2[key] = obj1[key]
}
}
extend(A,B)
//修改B对象中的引用类型数据 ,A对象也收到影响
B.dogs.color = 'red'
B.hobbies[0] = 'sing'
console.log(B)
console.log(A)
运行截图如下:修改B对象中的引用类型数据 ,A对象也收到影响,属于浅拷贝

3、ES6中新增的 Object.assign() 也是对象的浅拷贝
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。 Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。 注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
obj2.a.b // 2
上面代码中,源对象obj1的a属性的值是一个对象,Object.assign拷贝得到的是这个对象的引用。这个对象的任何变化,都会反映到目标对象上面。
4、扩展运算符(...)
利用扩展运算符可以在构造字面量对象时,进行克隆或者属性拷贝 ,属于浅拷贝
var obj = {a:1,b:{c:1}}
var obj2 = {...obj};
obj.a=2;
console.log(obj); //{a:2,b:{c:1}}
console.log(obj2); //{a:1,b:{c:1}}
obj.b.c = 2;
console.log(obj); //{a:2,b:{c:2}}
console.log(obj2); //{a:1,b:{c:2}}
5、Array.prototype.slice()
slice() 方法返回一个新的数组对象,这一对象是一个由 begin和 end(不包括end)决定的原数组的浅拷贝。原始数组不会被改变。
深拷贝是指, 修改B对象的属性和方法不会影响到A对象的属性和方法, 我们称之为深拷贝
以下几种情况都属于深拷贝:
1、默认情况下一个对象的属性如果是基本数据类型, 那么进行复制(拷贝),都是深拷贝
如果A对象的属性都是基本数据类型(Number、String等),此时要想深拷贝一份A给B,该怎么做呢,在这种要拷贝的对象A只有基本类型的数据时,只需要在内存中开辟一块空间存储B就行了。
let A = {
name: 'zyx',
age: 20
}
let B = {}
//定义一个函数,把A对象的属性复制一份给B
function extend(obj1,obj2){
for(var key in obj1){
obj2[key] = obj1[key]
}
}
extend(A,B)
console.log(B) // {name: "zyx", age: 20}
B.name = 'ls'
console.log(B) // {name: "ls", age: 20}
console.log(A) // {name: "zyx", age: 20}
这样就实现了深拷贝,如下图所示:

2、如果要拷贝的对象本身又包含了引用数据类型,即对象又包含数组或者对象,层层嵌套的情况下,想要实现对象的深拷贝,可以采用递归的方式进行深拷贝。
let A = {
name: 'ls',
age: 20,
hobbies: ['dance','basketball','read'],
dogs:{
name: '大黄',
color: 'yellow'
}
}
let B = {}
//定义一个函数,把A对象的属性复制一份给B
function extend(obj1,obj2){
for(var key in obj1){
var item = obj1[key]
if(item instanceof Array){
obj2[key] = []
extend(item,obj2[key])
}else if(item instanceof Object){
obj2[key] = {}
extend(item,obj2[key])
}else{
obj2[key] = item
}
}
}
extend(A,B)
B.dogs.color = 'red'
B.hobbies[0] = 'sing'
console.log(B)
console.log(A)
运行发现,修改B对象的引用数据类型,不会影响到A对象,完成深拷贝

我们可以对深拷贝的代码进行封装优化
function deepClone(obj){
let cloneObj = {}
for(let key in obj){
if(typeof obj[key] === 'object'){
cloneObj[key] = deepClone(obj[key])
}else{
cloneObj[key] = obj[key]
}
}
return cloneObj
}
3、通过JSON.stringify实现深拷贝
JSON.stringify()是目前前端开发过程中最常用的深拷贝方式,原理是把一个对象序列化成为一个JSON字符串,将对象的内容转换成字符串的形式再保存在磁盘上,再用JSON.parse()反序列化将JSON字符串变成一个新的对象。
var obj1 = {
a:1,
b:[1,2,3]
}
var str = JSON.stringify(obj1)
var obj2 = JSON.parse(str)
console.log(obj2); //{a:1,b:[1,2,3]}
obj1.a=2
obj1.b.push(4);
console.log(obj1); //{a:2,b:[1,2,3,4]}
console.log(obj2); //{a:1,b:[1,2,3]}
本文原创,欢迎到我的博客踩踩~ 地址:https://www.cnblogs.com/zyxnb/
总结JavaScript对象的深浅拷贝的更多相关文章
- Javascript 对象复制(深浅拷贝)
一.数据类型分类: 基本变量 引用类型 二.什么叫做指针指向 栈内存.堆内存.指针指向(如下红圈圈的斜线). 三.赋值.拷贝.引用区别? 赋值指一个变量赋予某个值,包含两种方式,一种是直接量,另一种, ...
- 关于Java的Object.clone()方法与对象的深浅拷贝
文章同步更新在个人博客:关于Java的Object.clone()方法与对象的深浅拷贝 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Object.clon ...
- javascript简单实现深浅拷贝
深浅拷贝知识在我们的日常开发中还算是用的比较多,但是之前的状态一直都是只曾听闻,未曾使用(其实用了只是自己没有意识到),所以今天来跟大家聊一聊js的深浅拷贝: 首先我们来了解一下javascript的 ...
- Javascript 中的深浅拷贝
工作中经常会遇到需要复制 JS 数据的时候,遇到 bug 时实在令人头疼:面试中也经常会被问到如何实现一个数据的深浅拷贝,但是你对其中的原理清晰吗?一起来看一下吧! 为什么会有深浅拷贝 想要更加透彻的 ...
- JavaScript中的深浅拷贝
深浅拷贝 在JS中,数据类型分为两类: 简单数据类型:Number.Boolean.String.undefined 引用数据类型:Array.Object.Function 简单数据类型通常 ...
- JavaScript对象的深浅复制
前言 从层次上来看,对象的复制可以简单地分为浅复制和深复制,顾名思义,浅复制是指只复制一层对象的属性,不会复制对象中的对象的属性,对象的深复制会复制对象中层层嵌套的对象的属性. 在复制对象时,除了要复 ...
- Object.clone()方法与对象的深浅拷贝
转载:[https://www.cnblogs.com/nickhan/p/8569329.html] 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Obj ...
- js对象的深浅拷贝
JS数据类型可以分为(ES5,暂时不考虑ES6): 简单数据类型:Number.String.undefined.boolean 复杂数据类型:Object.Array 简单的数据类型,往往是赋值操作 ...
- 在vue项目中遇到关于对象的深浅拷贝问题
一.问题 项目里新添加了一个多选的功能,其显示的数据都是从后端返回过来的,我们需要在返回来的数据外再额外添加一个是否选中的标记,我的选择是在返回正确的数据时将标记添加进去,然后push到数组中.然后就 ...
随机推荐
- css label两端对齐
上面这种效果很常见,实现的代码如下: html部分 <ul> <li class="detail_item"> <span class="d ...
- 梳理js数组去重中代码比较简洁的方案
一.es6 Set去重 function removal(arr) { return Array.from(new Set(arr)) } let arr=[1,2,1,3,4,5,5] remova ...
- 【转】JavaScript 3D图表
文章系本人原创,转载请保持完整性并注明出自<四火的唠叨> 在说3D图表以前,首先要明确两个概念,一个是数据的维度,一个是呈现数据载体的维度.对于数据的维度,一维的数据呈现,但是呈现的载体是 ...
- wepy怎么在生命周期中调用methods方法
很简单: 比如在 onLoad () { imgRemove(e) { this.methods.onRemove(e) } } 在methods中就可以直接调用属于它的方法, ...
- Java配置文件读取中文乱码问题
背景 这是我之前在做的用友服务对接开发,昨天领导拿给财务测试时告诉我有乱码,当时我第一想法是用友那边的编码格式有问题,因为还在做其他任务,我说等问一下用友他们用的什么编码格式我们这边改一下,然后今天早 ...
- 【X86】---X86处理器大小端的数据存储验证
之前也关注过大小端的存储,可能时间久了,加之又之前的电脑抽象换成了当前的处理器寄存器的值判断,导致自己总是有点蒙圈.看Spec手册的时候,有时会无法与手册中某个Bit的值与RU/RW工具读出来的对应上 ...
- 【UEFI&BIOS】---BIOS开机串口报"ERROR: C2:V1050007 IO 93B80003-9FB3-11D4-9A3A-0090273FC14D 6413FA18"的分析
intel的X86 CPU对运行错误的处理已经做的非常完善了,一般即使是开机卡死,跑飞等各种问题也会丢给你相关的提示信息,那么掌握这种错误的分析手段就显得至关重要.在实际开发的过程中,我遇到了一个错误 ...
- .net core2.2上传文件总结
总结一下.net core的上传文件操作,这里主要分上传到本地的也就是MVC的,另一种是上传到WebAPi的. 一.Web端 1.新建一个.net core mvc项目 2.这里的版本是.net co ...
- CSS中设置元素的圆角矩形
圆角矩形介绍 在CSS中通过border-radius属性可以实现元素的圆角矩形. border-radius属性值一共有4个,左上.右上.左下.右下. border-radius属性值规则如下:第一 ...
- 编程基础--XML约束
2020年新年第一天,不写一篇博客纪念一下都感觉对不起这个跨年 为什么会写一篇关于xml的博客呢?xml在编程中用的又不多,再多也用不着自己写约束文件,只要能看懂就行了不是吗?嗯,没别的原因,就是想研 ...