object.assign()的深拷贝还是浅拷贝?

一、参数对象为基本数据类型时

在调用object.assign()时,如果传入的参数对象为基本数据类型(number、string、boolean、null、undefined、NaN),则是浅拷贝。例如:

    
let obj1 = {a: 1, b: {c: 2}};
let obj2 = Object.assign({}, obj1);
obj1.b.c = 3;
console.log(obj2.b.c); // output: 3

上面的例子中,我们先定义了一个包含基本类型和对象类型的对象obj1,然后用object.assign()将obj1浅拷贝到一个空对象中。接着,我们改变了obj1中嵌套对象b的属性c的值,输出obj2中对应的属性c的值,发现也被改变了。

由此可以看出,因为obj1和obj2中的嵌套对象是同一个引用,所以改变一个也会影响其他的。

二、参数对象中有嵌套对象或数组

如果参数对象中有嵌套的对象或数组,那么使用object.assign()时会出现浅拷贝的情况。例如:

    
let obj1 = {a: 1, b: {c: 2}};
let obj2 = Object.assign({}, obj1);
obj1.b.d = [3, 4];
console.log(obj2.b.d); // output: [3, 4]

上面的例子中,我们先定义了一个包含基本类型和嵌套对象的对象obj1,然后用object.assign()将obj1浅拷贝到一个空对象中。接着,我们改变了obj1中嵌套对象b的属性d的值,输出obj2中对应的属性d的值,发现也被改变了。

由此可以看出,引用类型的赋值实际上是将指针复制一份,指向同一个地址,因此改变其中一个对象的嵌套属性或数组将会影响到另一个对象。

三、深拷贝的实现方法

在实际应用中,如果我们需要对嵌套对象或数组进行拷贝,需要使用深拷贝的方式。下面介绍几种常见的深拷贝实现方法:

1. JSON.parse()和JSON.stringify()

这是最常见的一种深拷贝方法,基于JSON.parse()解析字符串以及JSON.stringify()将对象转为字符串的特性,实现嵌套对象或数组的深拷贝。例如:

    
let obj1 = {a: 1, b: {c: 2}};
let obj2 = JSON.parse(JSON.stringify(obj1));
obj1.b.c = 3;
console.log(obj2.b.c); // output: 2

上面的例子中,我们先定义了一个包含基本类型和嵌套对象的对象obj1,然后使用JSON.parse()和JSON.stringify()对其进行深拷贝。接着,我们改变了obj1中嵌套对象b的属性c的值,输出obj2中对应的属性c的值,发现没有被改变。

但是需要注意的是,这种方法有以下缺点:

  • 只能处理JS支持的数据类型,即不能处理RegExp、Date实例、函数等非JSON数据类型。
  • 忽略undefined和Symbol类型的属性。
  • 不能实现循环引用的深拷贝,否则会抛出错误。

2. 递归拷贝

递归拷贝是指遍历对象或数组,对其中的嵌套对象或数组使用深拷贝的方式逐一拷贝,最终实现完全复制。例如:

    
function deepCopy(obj) {
    if(typeof obj !== 'object') {
        return obj;
    }
    let newObj = Array.isArray(obj) ? [] : {};
    for(let i in obj) {
        newObj[i] = deepCopy(obj[i]);
    }
    return newObj;
}
let obj1 = {a: 1, b: {c: 2}};
let obj2 = deepCopy(obj1);
obj1.b.c = 3;
console.log(obj2.b.c); // output: 2

上面的例子中,我们先定义了一个包含基本类型和嵌套对象的对象obj1,然后使用递归拷贝函数deepCopy()对其进行深拷贝。接着,我们改变了obj1中嵌套对象b的属性c的值,输出obj2中对应的属性c的值,发现没有被改变。

递归拷贝的好处是可以完全复制对象、数组以及其中包含的各种数据类型,没有限制,但是由于递归过程中会创建大量的对象或数组,因此如果拷贝的对象比较大或嵌套层数较深时,可能会影响性能。

3. Lodash的_.cloneDeep()

Lodash是一个实用的JS工具库,提供了丰富的函数,包括深拷贝的函数_.cloneDeep()。该函数可以对任何数据类型进行深拷贝,支持循环引用的拷贝,是比较常用的深拷贝方法之一。例如:

    
const _ = require('lodash');
let obj1 = {a: 1, b: {c: 2}};
let obj2 = _.cloneDeep(obj1);
obj1.b.c = 3;
console.log(obj2.b.c); // output: 2

上面的例子中,我们先定义了一个包含基本类型和嵌套对象的对象obj1,然后使用Lodash的_.cloneDeep()对其进行深拷贝。接着,我们改变了obj1中嵌套对象b的属性c的值,输出obj2中对应的属性c的值,发现没有被改变。

需要注意的是,使用Lodash需要先安装Lodash库,在Node.js中使用方式例如上面的代码。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/297469.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-28 12:16
下一篇 2024-12-28 12:16

相关推荐

  • JavaScript中的Object.getOwnPropertyDescriptors()

    一、简介 Object.getOwnPropertyDescriptors()是JavaScript中一个非常有用的工具。简单来说,这个方法可以获取一个对象上所有自有属性的属性描述…

    编程 2025-04-25
  • object.values()的用法

    一、用法介绍 在ES2017 (ECMA8)中,引入了新的方法object.values(),该方法可以将一个对象的所有属性的值以数组的形式返回。这个方法非常方便,因为在JavaS…

    编程 2025-04-25
  • 深入解析object.entries方法

    一、object.entries方法 在ECMAScript2017版规范中,新增了一个方法——Object.entries(),它可以将一个对象的键值对输出成一个数组,其中每个数…

    编程 2025-04-22
  • 深入了解JS Object.keys

    一、基本介绍 Object.keys()是JS的原生函数之一,它返回一个给定对象所有属性的字符数组,该数组包括对象本身的可枚举属性以及从原型链继承的可枚举属性(不包括属性值为und…

    编程 2025-04-12
  • object()takesnoparameters详解

    一、介绍 object()是Python中一个内置函数,可以用于创建一个空对象,并且该对象可以任意添加属性和方法。该函数不需要任何参数。 object()函数返回一个新对象。这个对…

    编程 2025-02-25
  • 详解.assign方法

    一、概述 JavaScript中的.assign()方法是用来将一个或多个对象的属性复制到另一个对象中。 //示例代码 let obj1 = {a: 1, b: 2}; let o…

    编程 2025-01-27
  • JS Object 遍历详解

    一、基础遍历方法 JavaScript 中的 Object 是一种键值对数据结构,使用起来非常灵活。在编程过程中,我们经常需要遍历 Object 以获取其中的值或者进行操作。下面将…

    编程 2025-01-27
  • 深入掌握JS中Object.keys()的使用

    一、Object.keys()的基本介绍 Object.keys()方法用于返回一个对象的所有属性名,返回值为一个数组,该数组包含了对象的所有可枚举属性。 该方法的语法如下: Ob…

    编程 2025-01-24
  • 深入理解Thymeleaf中的th:object

    一、th:object的概念 在Thymeleaf中,th:object是一种数据绑定表达式,它可以将一个Java对象与HTML表单元素进行绑定。通过th:object表达式,我们…

    编程 2025-01-24
  • Kotlin Object关键字全方位详解

    一、Object基础 Kotlin的Object关键字在很多方面类似于Java的静态类,但是在某些方面又有所不同。Object关键字允许我们创建单例对象(Singleton Obj…

    编程 2025-01-21

发表回复

登录后才能评论