乐闻世界logo
搜索文章和话题

JS 如何正确克隆一个对象

4个答案

1
2
3
4

当我们在JavaScript中克隆对象时,我们的目的是创建一个新的对象,它具有与原始对象相同的属性和值,但是在内存中占据不同的位置。这意味着,当我们修改新对象时,原始对象不会受到影响,反之亦然。以下是几种常用的克隆JavaScript对象的方法:

浅克隆(Shallow Clone)

Object.assign()

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

这里的Object.assign()方法会将所有可枚举的自有属性从一个或多个源对象复制到目标对象(在这里是一个空对象),然后返回目标对象。

Spread Operator (ES6)

javascript
let original = { a: 1, b: 2 }; let clone = { ...original };

扩展运算符...允许一个表达式在某处被扩展为多个参数(对于函数调用)或多个元素(对于数组字面量)或多个键值对(对于对象字面量)。

以上两种方法都是浅克隆,这意味着如果原始对象的属性值是一个对象,那么克隆对象的这个属性值仅仅是原始对象属性值的引用。如果修改了这个内部对象,原始对象和克隆对象都会受到影响。

深克隆(Deep Clone)

JSON方法

javascript
let original = { a: 1, b: { c: 3 } }; let clone = JSON.parse(JSON.stringify(original));

这种方法非常简单,可以用来深克隆一个对象。但是它有一些限制,例如它不会克隆函数,会忽略undefined,也不能处理循环引用的对象。

递归方式的深克隆

javascript
function deepClone(obj) { if (obj === null || typeof obj !== 'object') { return obj; } if (obj instanceof Date) { return new Date(obj.getTime()); } if (obj instanceof Array) { let arrCopy = []; obj.forEach((v, i) => arrCopy[i] = deepClone(v)); return arrCopy; } if (obj instanceof Object) { let copy = {}; Object.getOwnPropertyNames(obj).forEach(prop => { copy[prop] = deepClone(obj[prop]); }); return copy; } throw new Error('Unable to copy object!'); } let original = { a: 1, b: { c: 3 } }; let clone = deepClone(original);

这个方法会递归地克隆对象,包括其属性值是对象的情况。这样我们得到的克隆对象是完全独立于原始对象的。

库方法

有些JavaScript库(如 Lodash)提供了深克隆的功能。例如,使用Lodash的_.cloneDeep()

javascript
let _ = require('lodash'); let original = { a: 1, b: { c: 3 } }; let clone = _.cloneDeep(original);

这种方式非常简便,不需要自己编写复杂的深克隆逻辑,并且能够处理更复杂的情况,比如循环引用、特殊的对象类型等。

总结起来,选择哪种克隆方式取决于你需要的克隆深度和对象的复杂性。对于简单的情况,浅克隆可能就足够了。当对象结构更复杂,或者需要完全独立副本时,深克隆则是更好的选择。在实际工作中,我们通常倾向于使用成熟的库方法来处理这些事情,以减少bug和提高开发效率。

2024年6月29日 12:07 回复

在 ECMAScript 6 中,有一个Object.assign方法,它将所有可枚举自身属性的值从一个对象复制到另一个对象。例如:

shell
var x = {myProp: "value"}; var y = Object.assign({}, x);

但请注意,这是浅复制- 嵌套对象仍被复制为引用。

2024年6月29日 12:07 回复

使用 jQuery,您可以使用扩展进行浅复制

shell
var copiedObject = jQuery.extend({}, originalObject)

的后续更改copiedObject不会影响originalObject,反之亦然。

或者进行深层复制

shell
var copiedObject = jQuery.extend(true, {}, originalObject)
2024年6月29日 12:07 回复

根据MDN

  • 如果您想要浅复制,请使用Object.assign({}, a)
  • 对于“深度”复制,请使用JSON.parse(JSON.stringify(a))

不需要外部库,但您需要先检查浏览器兼容性

2024年6月29日 12:07 回复

你的答案