JavaScript 浅拷贝&深拷贝

浅拷贝

浅拷贝是指创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。换句话说,拷贝过程中,只复制了对象的第一层属性,而不是递归复制整个对象及其嵌套对象。

Object.assign()

let original = { a: 1, b: { c: 2 } };
let copy = Object.assign({}, original);

在浅拷贝中,当属性值是对象时(比如 b 是一个对象 { c: 2 }),拷贝后的对象中的这些属性仍然引用原始对象中相同的对象实例,而不是复制其内容。因此,如果你修改了拷贝后对象中的这些属性,实际上也会影响到原始对象中对应的属性,因为它们引用的是同一个对象实例。(即b拷贝时是地址而不是值,引用数据类型拷贝的是地址)

Spread 操作符 (...)

let original = { a: 1, b: { c: 2 } };
let copy = { ...original };

Array.slice()(仅适用于数组)

let originalArray = [1, 2, { a: 3 }];
let copyArray = originalArray.slice();

扩展运算符 (...)(仅适用于数组)

let originalArray = [1, 2, { a: 3 }];
let copyArray = [...originalArray];

注意事项:

嵌套对象的引用:浅拷贝只复制了第一层属性,如果原始对象的属性值是对象,那么拷贝后的对象仍然引用同一个嵌套对象。

原始对象引用问题:浅拷贝只会复制对象本身的属性,并不会复制它们背后的对象的实例。因此,对拷贝后的对象进行修改可能会影响到原始对象。

不适用于复杂对象:如果原始对象中有函数、RegExp 对象、Date 对象等特殊类型的属性,浅拷贝可能无法正确复制它们。



深拷贝

深拷贝与浅拷贝不同,它会递归地复制所有层级的对象及其属性,确保拷贝后的对象与原始对象完全独立,互不影响。

递归实现 这是一种基础的方法,通过递归遍历对象的所有属性,对每个属性进行复制,以确保深度复制整个对象及其嵌套对象。

let obj = {
    name: 'John',
    age: 30,
    address: {
        city: 'New York',
        postalCode: '10001'
    }
};

let copy = {};

function deepCopy(value) {
    // 简单示例的深度复制函数
    if (typeof value === 'object' && value !== null) {
        return JSON.parse(JSON.stringify(value)); // 简单的方式,不适用于包含函数、循环引用等情况
    } else {
        return value; // 基本类型直接返回
    }
}

// 遍历 obj 的所有属性,进行深度复制
for (let key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
        copy[key] = deepCopy(obj[key]);
    }
}

console.log(copy);

使用 JSON 序列化与反序列化 利用 JSON.stringify()JSON.parse() 可以实现简单的深拷贝,但要注意它有一些限制比如不能复制函数、正则表达式对象等特殊类型的属性。

 JSON.stringify() 方法将 JavaScript 对象转换为字符串

JSON.parse() 方法将数据转换为 JavaScript 对象

let deepCopy = JSON.parse(JSON.stringify(obj));

第三方库 如果需要处理更复杂的对象或者避免自己实现深拷贝的逻辑,可以使用第三方库,例如 Lodash 的 _.cloneDeep() 方法

lodash.cloneDeep | Lodash中文文档 | Lodash中文网 (lodashjs.com)

const _ = require('lodash');
let deepCopy = _.cloneDeep(obj);

注意事项:

性能问题:深拷贝可能会比浅拷贝消耗更多的时间和内存,特别是对于大型对象或对象层级很深的情况。

特殊类型的处理:一些特殊类型的属性(如函数、RegExp 等)可能需要额外的处理,以确保正确复制或避免因序列化而丢失信息。

循环引用:在处理可能存在循环引用的对象时,需要小心处理,以避免无限递归或栈溢出的问题。

  • 18
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
浅拷贝深拷贝是针对JavaScript中的对象属性为对象的情况而言的。浅拷贝只是复制了对象的引用,也就是复制了内存地址,所以拷贝后的对象和原对象会共用同一个内存地址,属性值的改变会相互影响。而深拷贝则是创建了一个完全独立的对象,拷贝了所有的属性和属性值,所以拷贝后的对象和原对象是完全独立的,互不影响。 在JavaScript中,可以通过不同的方法实现浅拷贝深拷贝浅拷贝可以使用手动实现、Object.assign()和拓展运算符等方法。手动实现的浅拷贝方法是遍历原始对象的属性,将属性值赋给新对象。Object.assign()方法可以将一个或多个源对象的属性复制到目标对象中,也可以用于实现浅拷贝。拓展运算符(...)也可以用于实现浅拷贝深拷贝则需要递归地复制对象的属性和属性值。可以通过手动实现一个深拷贝函数,在遍历原始对象的属性时,如果属性值是对象类型,则递归调用深拷贝函数进行复制。这样可以创建一个完全独立的对象,拷贝了所有的属性和属性值。 总结起来,浅拷贝只是复制了对象的引用,而深拷贝是创建了一个完全独立的对象。使用不同的方法可以实现浅拷贝深拷贝,根据具体的需求选择合适的方法进行使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [JavaScript深拷贝浅拷贝概念与用法实例分析](https://download.csdn.net/download/weixin_38735570/14820137)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [javascript深拷贝浅拷贝](https://blog.csdn.net/weixin_47417033/article/details/124899204)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值