JavaScript对象与数组的几种常见复制方法

 更新时间:2024年10月21日 08:35:08   作者:喝拿铁写前端  
在 JavaScript 开发中,对象和数组的复制是一个非常常见的操作,无论是函数参数传递、状态管理,还是避免不必要的副作用,了解和掌握各种复制方式至关重要,我们将系统梳理 JavaScript 中的几种常见复制方法,并对其应用场景进行详细说明,需要的朋友可以参考下

一、引用赋值:简单高效的数据共享

概念:引用赋值是 JavaScript 中最简单的操作。它不会真正创建对象的副本,而是让新的变量与原变量共享同一个内存地址。当你修改新变量时,原变量的数据也会被修改。

代码示例:

let person = { name: "Alice", age: 25 };
let newPerson = person;
newPerson.age = 30;
console.log(person.age);  // 输出 30

适用场景:

  • 在内存和性能上有要求时,可以避免不必要的复制。
  • 需要共享数据或保持同步的场景,如状态管理或配置共享。

优点:

  • 高效、节省内存。

缺点:

  • 修改新变量会影响原对象,容易引发副作用。

二、浅拷贝:复制顶层属性

浅拷贝创建一个新对象,复制原对象的顶层属性,但如果属性是引用类型(如对象、数组),它们仍然指向原来的内存地址。

1. 扩展运算符 ...

代码示例:

let person = { name: "Alice", age: 25, details: { city: "New York" } };
let newPerson = { ...person };
newPerson.details.city = "Los Angeles";
console.log(person.details.city);  // 输出 "Los Angeles"

适用场景:

  • 对象结构简单,或仅需浅层修改的情况。

2. Object.assign()

Object.assign() 也是一种浅拷贝方式,适用于将多个对象合并到目标对象。

代码示例:

let target = { a: 1 };
let source = { b: 2 };
let newObject = Object.assign(target, source);

适用场景:

  • 当你需要将多个对象合并时,尤其适合对象合并操作。

3. Array.prototype.slice() 和 concat()

对于数组,可以使用 slice() 或 concat() 来创建浅拷贝。

代码示例:

let arr = [1, 2, 3];
let shallowCopy = arr.slice();

适用场景:

  • 适合处理简单数组,不涉及深层次数据。

三、深拷贝:完整的对象复制

深拷贝是指对对象或数组进行递归复制,确保所有层级的嵌套对象都有独立的副本。修改新对象不会影响原对象。

1. 递归实现深拷贝

代码示例:

function deepClone(obj) {
    if (obj === null || typeof obj !== 'object') return obj;
    let copy = Array.isArray(obj) ? [] : {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            copy[key] = deepClone(obj[key]);
        }
    }
    return copy;
}

适用场景:

  • 当对象结构复杂,需要完全独立的副本时。

2. JSON.parse(JSON.stringify())

这种方式可以快速实现深拷贝,但它有一些局限性,如无法复制函数、DateRegExp 等特殊类型。

代码示例:

let original = { a: 1, b: { c: 2 } };
let copy = JSON.parse(JSON.stringify(original));

适用场景:

  • 适合简单的对象结构,不包含特殊类型。

3. structuredClone()

structuredClone() 是一种更高级的深拷贝方法,可以处理 DateMapSet 等复杂对象类型。

代码示例:

let original = { a: 1, b: new Date(), c: new Map([[1, 'one']]) };
let copy = structuredClone(original);

适用场景:

  • 需要复制复杂对象,包括 MapSet 等高级数据结构。

四、特殊数据类型的复制方法

1. Object.create()

Object.create() 用于创建一个新的对象,该对象继承自指定的原型对象,而不是复制原对象的属性。

代码示例:

let person = { name: "Alice", age: 25 };
let newPerson = Object.create(person);

适用场景:

  • 用于原型继承,而不是单纯复制。

2. Map 和 Set 的复制

Map 和 Set 提供直接构造函数,可以创建它们的浅拷贝。

代码示例:

let originalMap = new Map([[1, 'one']]);
let copyMap = new Map(originalMap);

适用场景:

  • 需要复制 Map 或 Set 时,适合浅拷贝操作。

五、冻结对象:防止对象修改

虽然不是一种拷贝方式,但 Object.freeze() 可以防止对象的属性被修改。这是一种浅冻结,嵌套对象仍然可以修改。

代码示例:

let obj = { name: "Alice", details: { age: 25 } };
Object.freeze(obj);

适用场景:

  • 需要防止对象被修改时,尤其适合配置或常量对象。

六、总结与最佳实践

在 JavaScript 中,不同的复制方式适用于不同的场景。以下是总结:

  • 引用赋值:高效、内存占用少,但会产生副作用,适合数据共享。
  • 浅拷贝:适用于简单对象或数组,性能较好,但无法处理深层嵌套对象。
  • 深拷贝:适用于复杂对象的完全复制,保证数据独立,但性能开销较大。
  • 特殊数据类型的复制:针对 MapSetDate 等复杂类型,选择合适的复制方式。
  • 冻结对象:适用于需要确保对象不可修改的场景,如配置文件或常量。

在实际项目中,选择合适的复制方式可以大幅提升代码的效率和可维护性。针对不同的需求,深度理解这些方法的适用场景,能够帮助你编写出更加健壮、可维护的代码。

通过这篇文章,我们梳理了 JavaScript 中从引用赋值到深拷贝的各种方法及其应用场景。我们在开发过程中,需要灵活选择合适的方式,确保数据的有效管理和高效处理。

以上就是JavaScript对象与数组的几种常见复制方法的详细内容,更多关于JavaScript对象与数组复制的资料请关注脚本之家其它相关文章!

相关文章

  • JS实现的数组去除重复数据算法小结

    JS实现的数组去除重复数据算法小结

    这篇文章主要介绍了JS实现的数组去除重复数据算法,总结分析了4种比较常见的数组去重复算法及相关使用技巧,需要的朋友可以参考下
    2017-11-11
  • 原生JS实现拖拽功能

    原生JS实现拖拽功能

    这篇文章主要为大家介绍了JS实现拖拽功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • javascript正则表达式模糊匹配IP地址功能示例

    javascript正则表达式模糊匹配IP地址功能示例

    这篇文章主要介绍了javascript正则表达式模糊匹配IP地址功能,结合简单实例形式演示了JS模糊匹配IP地址的实现方法,涉及针对数字及字符串的相关正则判定与匹配操作技巧,需要的朋友可以参考下
    2017-01-01
  • 微信小程序自定义toast的实现代码

    微信小程序自定义toast的实现代码

    这篇文章主要介绍了微信小程序自定义toast的实现代码,本文以toast为例通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-11-11
  • webpack配置proxyTable时pathRewrite无效的解决方法

    webpack配置proxyTable时pathRewrite无效的解决方法

    这篇文章主要介绍了webpack配置proxyTable时pathRewrite无效的解决方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • JavaScript实现轮播图效果代码实例

    JavaScript实现轮播图效果代码实例

    这篇文章主要介绍了JavaScript实现轮播图效果代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • javascript实现多级联动下拉菜单的方法

    javascript实现多级联动下拉菜单的方法

    这篇文章主要介绍了javascript实现多级联动下拉菜单的方法,通过javascript自定义函数实现对多级联动下拉菜单的操作,是非常实用的技巧,需要的朋友可以参考下
    2015-02-02
  • 为调试JavaScript添加输出窗口的代码

    为调试JavaScript添加输出窗口的代码

    调试JavaScript是一件很麻烦的事,尽管有很多很好用的调试工具,但有时候想要跟踪值的变化,但即不想中断脚本执行,也不想用alert显示值信息,这种情况下,一般的做法是在页面上添加一个DIV或者其它元素,然后再往里面添加调试信息。
    2010-02-02
  • js实现省市联动效果的简单实例

    js实现省市联动效果的简单实例

    本篇文章主要是对js实现省市联动效果的简单实例进行了介绍,需要的朋友可以过来,希望对大家有所帮助
    2014-02-02
  • 给页面渲染时间加速 干掉Dom Level 0 Event

    给页面渲染时间加速 干掉Dom Level 0 Event

    我们去掉事件绑定的逻辑,发现只渲染dom元素,不绑定事件的时间,仅仅125ms,可见事件绑定的时间消耗还是很大的 ,尤其是第一种方式,也就是Dom Level 0 Event,最为耗时
    2012-12-12

最新评论