浅拷贝和深拷贝

文章详细阐述了JavaScript中的基本数据类型和引用数据类型,以及它们在内存中如何存储。接着讨论了浅拷贝和深拷贝的概念,分别通过Object.assign、扩展运算符、自定义函数以及JSON.stringify和lodash库的_.cloneDeep方法展示了实现方式,并分析了各自的优缺点。
摘要由CSDN通过智能技术生成

1.前言:数据类型

数据类型分为基本数据类型和引用数据类型,理解这两种数据类型的特点,对理解深拷贝和浅拷贝至关重要

1.1 基本数据类型

基本数据类型:Boolean、Null、Undefined、Number、String、BigInt、Symbol
基本数据类型都是存储在栈(stack)内存中,栈具有先进后出的特点,基本数据类型占用空间小、大小固定,通过按值来访问,属于被频繁使用的数据。

let a=1;
let b=a;
a=3;
console.log(a,b)

输出结果:
在这里插入图片描述
基本数据类型的赋值,赋值后两个变量互不影响,b复制的是a的原始值,它们存储在独立的的栈空间中,因此修改了的值,b的值不会受到影响

1.2 引用数据类型

引用数据类型:Object(包括 Object 、Array 、Function)
引用数据类型占据空间大、大小不固定,存放在栈中会有性能的问题。引用数据类型在栈中保存了一份指针,该指针指向对应的数据在堆中的起始地址,当解释器寻找引用值时,会首先检索其在栈中的地址,通过地址从堆中获得数据。

obj={
 age:21
}
let objCopy=obj;
objCopy.age=22;
console.log(obj,objCopy)

在这里插入图片描述
引用类型的赋值,在栈中复制了一份引用类型的地址指针,两个变量指向的还是同一个对象,所以修改objCopy.age时,obj.age也会改变

2.浅拷贝和深拷贝

2.1 浅拷贝

浅拷贝是指,一个新的对象对原始对象的属性值进行精确地拷贝,如果拷贝的是基本数据类型,拷贝的就是基本数据类型的值,如果是引用数据类型,拷贝的就是内存地址。如果其中一个对象的引用内存地址发生改变,另一个对象也会发生变化。

实现浅拷贝

  • Object.assign()
    Object.assign() 是ES6中对象的拷贝方法,接受的第一个参数是目标对象,其余参数是源对象,用法: Object.assign(target, source_1, ···) ,该方法可以实现浅拷贝,也可以实现一维对象的深
    拷贝。
let target={a:1}
let object1={b:2,c:3}
Object.assign(target,object1)
console.log(target)//{a:1,b:2,c:3
  • 扩展运算符
let obj1 = {a:1,b:{c:1}}
let obj2 = {...obj1};
obj1.a = 2;
console.log(obj1); //{a:2,b:{c:1}}
console.log(obj2); //{a:1,b:{c:1}}
  • 手写实现浅拷贝函数
// 浅拷贝的实现;
function shallowCopy(object) {
   	// 只拷贝对象
   	if (!object || typeof object !== "object") return;
   	// 根据 object 的类型判断是新建一个数组还是对象
   	let newObject = Array.isArray(object) ? [] : {};
   	// 遍历 object,并且判断是 object 的属性才拷贝
   	for (let key in object) {
   		if (object.hasOwnProperty(key)) {
   		      newObject[key] = object[key];
   		   }
   	}
   	return newObject;
}
2.2 深拷贝

深拷贝相对浅拷贝而言,如果遇到属性值为引用类型的时候,它新建一个引用类型并将对
应的值复制给它,因此对象获得的一个新的引用类型而不是一个原有类型的引用,所以彼此的修改,互不影响。

  • JSON.stringify()
    JSON.parse(JSON.stringify(obj)) 是目前比较常用的深拷贝方法之一,它的原理就是利用JSON.stringify 将 js 对象序列化(JSON字符串),再使用 JSON.parse 来反序列化(还原) js 对
    象。这个方法可以简单粗暴的实现深拷贝,但是还存在问题,拷贝的对象中如果有函数,undefined,symbol,当使用过 JSON.stringify() 进行处理之后,都会消失。
let obj2={
  a:1,
  b:{
    c:2
  }
}
let obj3 = JSON.parse(JSON.stringify(obj2));
obj2.b.c=3;
console.log(obj2)//{a:1,b:{c:3}}
console.log(obj3)//{a:1,b:{c:2}}
  • 函数库lodash的_.cloneDeep方法
var  _=require('lodash')
let obj2={
 a:1,
 b:{
   c:2
 }
}
var obj4=_.cloneDeep(obj2);
console.log(obj2.b===obj4.b)//false
  • 手写实现深拷贝函数
// 深拷贝的实现
function deepCopy(object) {
   	if (!object || typeof object !== "object") return;
   	let newObject = Array.isArray(object) ? [] : {};
   	for (let key in object) {
   		if (object.hasOwnProperty(key)) {
   		  newObject[key] =typeof object[key] === "object" ? deepCopy(object[key]) : object[key];
       	}
   	}
   	return newObject;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值