【JavaScript知识点学习笔记】深浅拷贝

深浅拷贝是JavaScript一个非常经典的知识点,每次提到深浅拷贝我总是没办法特别清楚的表述出来,包括很多其他的知识点,其实是会的,但是没办法讲的很清楚,学习了费曼学习法,决定在复盘知识点的时候,每天找人讲解知识点,如果我能表达出来且让对方能听明白我讲的东西才算过关! !

首先简单介绍一些 深拷贝和浅拷贝,他们是JavaScript中复制对象的两种类型。

1.浅拷贝:浅拷贝只复制对象的第一层属性,而不复制嵌套对象的引用。这意味着如果原始对象包含嵌套对象,浅拷贝后的对象仍然会共享这些嵌套对象的引用。可以使用`Object.assign()`或展开运算符(`...`)来进行浅拷贝。

// 浅拷贝示例
//1.使用Object.assign
const originalObj = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, originalObj);

//2. 使⽤展开运算符
let obj1 = { a: 1, b: 2 };
let obj2 = { ...obj1 };
console.log(obj2); // { a: 1, b: 2 }

2.深拷贝:深拷贝会递归地复制所有嵌套对象及其属性,创建一个全新的对象,不共享任何引用。这样可以确保修改深拷贝后的对象不会影响原始对象。常见的深拷贝方法包括使用`JSON.parse(JSON.stringify())`、第三方库如Lodash的`_.cloneDeep()`等。

// 深拷贝示例
const originalObj = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(originalObj));

浅拷贝只复制对象的顶层属性

而深拷贝会递归复制所有嵌套属性,确保复制后的对象是完全独立的


以下是更深入的讲解一下深拷贝

深拷贝的几种实现方式:

1.上面的JSON.parse(JSON.stringify())

2. 使⽤递归实现深拷贝函数

function deepClone(obj) {

if (obj === null || typeof obj !== 'object') {

return obj;

}

let clone = Array.isArray(obj) ? [] : {};


for (let key in obj) {

if (obj.hasOwnProperty(key)) {

clone[key] = deepClone(obj[key]);

 }

}

return clone;

}

let obj1 = {

a: 1,

b: { c: 2 }

};

let obj2 = deepClone(obj1);

obj2.b.c = 3;

console.log(obj1.b.c); // 2

console.log(obj2.b.c); // 3

3. 使⽤第三⽅库 lodash 的 cloneDeep() ⽅法

const _ = require('lodash');

let obj1 = {

a: 1,

b: { c: 2 }

};

let obj2 = _.cloneDeep(obj1);

obj2.b.c = 3;

console.log(obj1.b.c); // 2

console.log(obj2.b.c); // 3

!!注意:其中JSON.parse(JSON.stringify())⽅法是有局限性的

  • 会忽略 undefined
  • 不能序列化函数
  • 不能解决循环引⽤的对象

1. ⽆法处理函数: JSON.stringify() ⽅法在序列化对象时会忽略函数属性,因为函数不符合JSON 格式的数据类型。经过序列化和反序列化后,函数属性会丢失。

let obj = {

name: 'poetry',

sayHello: function() {

console.log('Hello!');

}

};

let serializedObj = JSON.stringify(obj);

let clonedObj = JSON.parse(serializedObj);

console.log(clonedObj.name); // 'poetry'

console.log(typeof clonedObj.sayHello); // 'undefined'

2. ⽆法处理循环引⽤:如果对象存在循环引⽤,即对象内部包含对⾃身的引⽤, JSON.stringify() ⽅法⽆法正确处理,会导致循环引⽤的属性被序列化为 null 。

let obj = {

name: 'poetry'

};

obj.self = obj;

let serializedObj = JSON.stringify(obj);

console.log(serializedObj); // {"name":"poetry","self":null}

3. ⽆法处理特殊对象: JSON.stringify() ⽅法⽆法序列化某些特殊对象,如 Date 对象、正则表达式、 Map 、 Set 等,它们在序列化过程中会转换成空对象。

let obj = {

now: new Date(),

regex: /[a-z]+/,

set: new Set([1, 2, 3]),

map: new Map([[1, 'one'], [2, 'two']])

};

let serializedObj = JSON.stringify(obj);

console.log(serializedObj); // {"now":{},"regex":{},"set":{},"map":{}}

4. ⽆法处理 undefined 属性: JSON.stringify() ⽅法在序列化对象时会忽略 undefined 属性,序列化后的结果不包含该属性。

let obj = {

name: 'poetry',

age: undefined

};

let serializedObj = JSON.stringify(obj);

console.log(serializedObj); // {"name":"poetry"}

在使⽤ JSON.stringify() 进⾏深拷⻉时,需要注意上述局限性,并确保对象不包含函数、循环引⽤或特殊对象,并且不需要保留 undefined 属性。对于包含上述情况的对象,应使⽤其他⽅法实现深拷⻉。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值