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/zh-hant/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

發表回復

登錄後才能評論