js对象的赋值,浅拷贝,深拷贝区分和使用场景

一、前置知识

js在定义变量的时候,变量会被存储堆和栈中,基本数据类型(String,Number,Null,Undefined,Boolean)存储在栈中,引用数据类型(Object、Array、Function、Data等)存储在堆中,但是在栈中存储了指向堆数据的指针(内存地址)。

二、区分

1.赋值

赋值没有创建新对象仅仅是拷贝了原对象的指针。所以把obj赋值给obj2,只拷贝了栈中的内存地址,指向同一个堆。

(这里懒得画图就借用其他博主的博客来举例了,复制=赋值)

var obj = {name:'ConardLi'};
var obj2 = obj;
obj2.name = 'code秘密花园';
console.log(obj.name); // code秘密花园

同理我们赋值一个基本数据类型

var name = 'ConardLi';
var name2 = name;
name2 = 'code秘密花园';
console.log(name); // ConardLi;

 

把name2赋值给name,基础数据类型存放在栈中,所以修改他们两个的数据互不影响。

2.浅拷贝

 浅拷贝是创建一个新对象,这个对象仅对原对象的属性进行拷贝,属性值是基本类型时,拷贝的是原数据,属性值是引用类型时,拷贝的是指针。(可以根据上图方便理解)。也可以理解为浅拷贝只拷贝了栈内存中的数据。所以当我们修改基本数据类型时,因为浅拷贝复制了一份栈中的数据,所以两者不会有影响,但是修改引用数据类型时,就会对原数据产生影响。

下面代码举例:

let obj = {
    a: 1,
    b: { c: 3 }
};

// 借助对象的方法assign实现浅拷贝
let obj2 = Object.assign({}, obj)

obj.a = 2;
obj.b.c = 4;

console.log(obj); //{ a: 2, b: { c: 4 } }
console.log(obj2); //{ a: 1, b: { c: 4 } }

3.深拷贝

深拷贝创建一个新对象,但不仅对原对象的属性进行拷贝,还在堆内存中开辟一个新的地址用来存储新对象,所以新对象和原对象互不影响,修改其中一个另一个也不会有变化

下面代码举例:

let obj = {
    a: 1,
    b: { c: 3 }
};

// 进行深拷贝
let obj2 = JSON.parse(JSON.stringify(obj));

obj.a = 2;
obj.b.c = 4;

console.log(obj); //{ a: 2, b: { c: 4 } }
console.log(obj2); //{ a: 1, b: { c: 3 } }

注意:对于包含函数、正则表达式、Symbol等特殊类型的对象,使用 JSON.stringify()JSON.parse() 进行深拷贝可能会丢失这些特殊类型的信息。在实际开发中,可以使用第三方库(如 lodash 中的 _.cloneDeep() 方法)来实现更复杂的深拷贝需求。

三、使用场景

赋值:原对象仅使用一次(被修改也不产生副作用)。

浅拷贝:原对象需多次使用(被修改会导致后续使用数据不准确),适用于简单的对象或数组结构,不包含嵌套的引用类型属性。

深拷贝:原数据需多次使用(被修改会导致后续使用数据不准确),适用为了避免原始对象和复制后的对象之间相互影响的场景,且属性含有引用类型。注意深拷贝会消耗更多的内存和性能,特别是对于复杂、嵌套层级深的对象和数组。

图片引用自【JS 进阶】你真的掌握变量和类型了吗 - 掘金

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值