百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

浅拷贝与深拷贝全面解析及实战(浅拷贝和深拷贝的实现方式)

wptr33 2025-03-20 20:08 13 浏览

在JavaScript学习中,拷贝是很重要的一个知识点。拷贝主要分为浅拷贝(Shallow Copy)和深拷贝(Deep Copy)。本文将阐述两者的概念,还将通过手写示例深入探讨如何实现这两种拷贝方式,以及它们在实际应用中的考量。

浅拷贝:表面级复制

浅拷贝只复制对象的第一层属性,对于嵌套对象或数组,仅复制它们的引用,导致原对象和拷贝对象在这些部分仍然共享数据。

实现方法:

let obj = {
    a: 1, 
    b: [1,2,3]
}
  • Object.create(obj) let obj2 = Object.create(obj);
  • Object.assign({}, obj) let obj2 = Object.assign({}, obj);
  • Array.concat()
  • const arr = [1, 2, 3];
    const newArr = [].concat(arr);
    console.log(newArry); // 输出 [1, 2, 3]
    • Array.slice(0)
        const arr = [1, 2, 3];
        const newArr = original.slice(0);
        console.log(newArr); // 输出 [1, 2, 3]
    • Array.toReverse().reverse()
        const arr = [1, 2, 3];
        const newArr = arr.toReversed().reverse();
        console.log(newArr); // 输出 [1, 2, 3]
    • 扩展运算符 ...args
        const arr = [1, 2];
        const newArr = [...arr];
        console.log(newArr); 

    手写浅拷贝示例

    • 实现原理:forin循环遍历对象中的所有属性借助hasOwnProperty()方法,判断属性是否为对象显式属性
    • 实现代码:
    function shallowCopy(obj) {
        let newObj = Array.isArray(obj) ? [] : {};
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                newObj[key] = obj[key];
            }
        }
        return newObj;
    }

    特点

    • 执行速度快,占用资源少。
    • 适用于简单对象或不需要完全独立拷贝的场景。
    • 不适用于包含嵌套对象或数组的复杂结构,因为更改嵌套数据会影响原对象。

    深拷贝:彻底复制

    深拷贝会递归地复制对象的所有层次,包括嵌套的数组和对象,从而确保原对象和拷贝对象完全独立,互不影响。

    实现方法:

    • JSON.parse(JSON.stringify(obj))(有局限性)
         const original = { a: 1, b: { c: 2 } };
         const copy = JSON.parse(JSON.stringify(original));
         console.log(copy); // 输出 { a: 1, b: { c: 2 } }
    • structuredClone(obj)(较新,但仍有限制)
        const original = { a: 1, b: { c: 2 } };
        const copy = structuredClone(original);
        console.log(copy); // 输出 { a: 1, b: { c: 2 } }
    • 自定义递归函数实现

    手写深拷贝示例

    • 实现原理:
    1. forin循环遍历对象中的所有属性
    2. 借助hasOwnProperty()方法,判断属性是否为对象显式属性
    3. 判断属性值类型,递归调用深拷贝函数
    • 实现代码:
    function deepCopy(obj) {
        if (!obj || typeof obj !== 'object') {
            return obj;
        }
        let newObj = Array.isArray(obj) ? [] : {};
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                newObj[key] = deepCopy(obj[key]);
            }
        }
        return newObj;
    }


    特点

    • 创建完全独立的副本,适用于复杂数据结构。
    • 相对耗时和占用更多资源,尤其是面对深度嵌套对象。

    实践比较与选择

    • 性能与资源:浅拷贝因为操作简单,执行效率高,适合快速复制;深拷贝则因递归复制所有层级,成本较高,但在需要完全独立数据副本时不可或缺。
    • 应用场景:对于简单的对象复制或状态克隆,浅拷贝足矣;而在需要确保数据完全隔离,避免外部修改影响内部状态时,深拷贝是更好的选择。
    • 注意事项:使用JSON.stringify()和JSON.parse()进行深拷贝虽简便,但存在局限性(如不支持函数、Symbol、循环引用等)。自定义深拷贝时,循环引用的处理是一个常见的挑战。

    结论

    浅拷贝和深拷贝各有千秋,关键在于根据具体需求选择合适的拷贝策略。了解它们的实现机制,不仅能提升代码的健壮性,还能有效避免潜在的数据篡改问题。通过手写实现深浅拷贝,不仅可以加深对JavaScript对象的理解,也能在特定场景下提供灵活的解决方案。


    文章转自:
    https://juejin.cn/post/7379151898567622696

    相关推荐

    每天一个编程技巧!掌握这7个神技,代码效率飙升200%

    “同事6点下班,你却为改BUG加班到凌晨?不是你不努力,而是没掌握‘偷懒’的艺术!本文揭秘谷歌工程师私藏的7个编程神技,每天1分钟,让你的代码从‘能用’变‘逆天’。文末附《Python高效代码模板》,...

    Git重置到某个历史节点(Sourcetree工具)

    前言Sourcetree回滚提交和重置当前分支到此次提交的区别?回滚提交是指将改动的代码提交到本地仓库,但未推送到远端仓库的时候。...

    git工作区、暂存区、本地仓库、远程仓库的区别和联系

    很多程序员天天写代码,提交代码,拉取代码,对git操作非常熟练,但是对git的原理并不甚了解,借助豆包AI,写个文章总结一下。Git的四个核心区域(工作区、暂存区、本地仓库、远程仓库)是版本控制的核...

    解锁人生新剧本的密钥:学会让往事退场

    开篇:敦煌莫高窟的千年启示在莫高窟321窟的《降魔变》壁画前,讲解员指着斑驳色彩说:"画师刻意保留了历代修补痕迹,因为真正的传承不是定格,而是流动。"就像我们的人生剧本,精彩章节永远...

    Reset local repository branch to be just like remote repository HEAD

    技术背景在使用Git进行版本控制时,有时会遇到本地分支与远程分支不一致的情况。可能是因为误操作、多人协作时远程分支被更新等原因。这时就需要将本地分支重置为与远程分支的...

    Git恢复至之前版本(git恢复到pull之前的版本)

    让程序回到提交前的样子:两种解决方法:回退(reset)、反做(revert)方法一:gitreset...

    如何将文件重置或回退到特定版本(怎么让文件回到初始状态)

    技术背景在使用Git进行版本控制时,经常会遇到需要将文件回退到特定版本的情况。可能是因为当前版本出现了错误,或者想要恢复到之前某个稳定的版本。Git提供了多种方式来实现这一需求。...

    git如何正确回滚代码(git命令回滚代码)

    方法一,删除远程分支再提交①首先两步保证当前工作区是干净的,并且和远程分支代码一致$gitcocurrentBranch$gitpullorigincurrentBranch$gi...

    [git]撤销的相关命令:reset、revert、checkout

    基本概念如果不清晰上面的四个概念,请查看廖老师的git教程这里我多说几句:最开始我使用git的时候,我并不明白我为什么写完代码要用git的一些列指令把我的修改存起来。后来用多了,也就明白了为什么。gi...

    利用shell脚本将Mysql错误日志保存到数据库中

    说明:利用shell脚本将MYSQL的错误日志提取并保存到数据库中步骤:1)创建数据库,创建表CreatedatabaseMysqlCenter;UseMysqlCenter;CREATET...

    MySQL 9.3 引入增强的JavaScript支持

    MySQL,这一广泛采用的开源关系型数据库管理系统(RDBMS),发布了其9.x系列的第三个更新版本——9.3版,带来了多项新功能。...

    python 连接 mysql 数据库(python连接MySQL数据库案例)

    用PyMySQL包来连接Python和MySQL。在使用前需要先通过pip来安装PyMySQL包:在windows系统中打开cmd,输入pipinstallPyMySQL ...

    mysql导入导出命令(mysql 导入命令)

    mysql导入导出命令mysqldump命令的输入是在bin目录下.1.导出整个数据库  mysqldump-u用户名-p数据库名>导出的文件名  mysqldump-uw...

    MySQL-SQL介绍(mysql sqlyog)

    介绍结构化查询语言是高级的非过程化编程语言,允许用户在高层数据结构上工作。它不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以具有完全不同底层结构的不同数据库系统,可以使用相同...

    MySQL 误删除数据恢复全攻略:基于 Binlog 的实战指南

    在MySQL的世界里,二进制日志(Binlog)就是我们的"时光机"。它默默记录着数据库的每一个重要变更,就像一位忠实的史官,为我们在数据灾难中提供最后的救命稻草。本文将带您深入掌握如...