VIP用户交流群:462197261 收藏本站北冥有鱼 互联网前沿资源第一站 助力全行业互联网+
在线客服:78895949
tonglan
  • 当前位置:
  • 怎么使用javascript深度拷贝一个数组

    有两种数组拷贝类型:浅拷贝 & 深拷贝。浅拷贝只会拷贝数组的第一层,剩下的会引用。如果你需要一个嵌套的数组的拷贝,那需要你去深度拷贝这个数组。深拷贝,选择JSON方法或者Lodsh库吧

    const numbers = [1, [2], [3, [4]], 5];
    // Using JavaScript
    JSON.parse(JSON.stringify(numbers));
    // Using Lodash
    _.cloneDeep(objects);

    数组是引用类型

    为了搞清楚为什么有两种类型的拷贝,我们来深度了解一下基础知识然后解释什么是引用类型。
    与原始类型(number、string)不同,数组是引用类型。这意味着当你把一个数组赋值给一个变量,你是将数组的内存地址而非数组本身赋给变量。

    拷贝值类型

    这里没什么大不了的,我们创建一个value的拷贝。当我们改变valueCopy的值,它不会影响原来的value值。同理,当我们改变原来的值它也不会影响拷贝后的值。很好👍

    let value = 3;
    let valueCopy = value; // create copy
    console.log(valueCopy); // 3
    // Change valueCopy
    valueCopy = 100
    console.log(valueCopy); // 100
    // ✅ Original NOT affected 
    console.log(value); // 3

    拷贝引用类型

    好的,这里就会有点奇怪了!我们用同样的方法拷贝数组。

    let array = [1,2,3];
    let arrayCopy = array; // create copy
    console.log(arrayCopy); // [1,2,3];
    // Change 1st element of the array
    arrayCopy[0] = '👻';
    console.log(arrayCopy); // [ '👻', 2, 3 ]
    // ❌Original got affected
    console.log(array); // [ '👻', 2, 3 ]

    为什么原来的数组也受到了影响呢?好了,是因为:你拷贝的不是你拷贝的。说人话,意思就是你拷贝的只是指向数组内存空间的指针。引用类型不包含值,它们是指向内存中值的指针。

    拷贝引用类型的方法

    解决方法就是拷贝值而不是指针。

    let array = [1,2,3];
    let arrayCopy = [...array]; // create TRUE copy
    console.log(arrayCopy); // [1,2,3];
    // Change 1st element of the array
    arrayCopy[0] = '👻';
    console.log(arrayCopy); // [ '👻', 2, 3 ]
    // ✅ Original NOT affected 
    console.log(array); // [ 1, 2, 3 ]

    浅 & 深 拷贝

    当我使用展开扩展符号...来拷贝一个数组,我只是浅拷贝了一个数组。如果数组是嵌套或者多维的,这就不奏效了。

    let nestedArray = [1, [2], 3];
    let arrayCopy = [...nestedArray];
    // Make some changes
    arrayCopy[0] = '👻'; // change shallow element
    arrayCopy[1][0] = '💩'; // change nested element
    console.log(arrayCopy); // [ '👻', [ '💩' ], 3 ]
    // ❌ Nested array got affected
    console.log(nestedArray); // [ 1, [ '💩' ], 3 ]

    如上,浅拷贝首层数组表现良好,然而,更改了嵌套数组元素,原始数组也受到影响💩。为了解决这个问题,就要用到深拷贝了。

    let nestedArray = [1, [2], 3];
    let arrayCopy = JSON.parse(JSON.stringify(nestedArray));
    // Make some changes
    arrayCopy[0] = '👻'; // change shallow element
    arrayCopy[1][0] = '💩'; // change nested element
    console.log(arrayCopy); // [ '👻', [ '💩' ], 3 ]
    // ✅ Nested array NOT affected
    console.log(nestedArray); // 1, [ 2 ], 3 ]

    所以,这就完事了吗?要不要手写一个深拷贝引用类型的方法?

    const deepClone = obj => {
    const isObject = args => (typeof args === 'object' || typeof args === 'function') && typeof args !== null
    if (!isObject) throw new Error('Not Reference Types')
    let newObj = Array.isArray(obj) ? [...obj] : { ...obj }
    Reflect.ownKeys(newObj).map(key => {
    newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    })
    return newObj
    }

    文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,

    您可能感兴趣的文章:

    • JavaScript中十种一步拷贝数组的方法实例详解
    • JS实现数组深拷贝的方法分析
    • js实现数组和对象的深浅拷贝
    • JavaScript数组深拷贝和浅拷贝的两种方法
    • javascript数组操作(创建、元素删除、数组的拷贝)

    广而告之:
    热门推荐:
    MySQL存储文本和图片的方法

    Oracle中大文本数据类型 Clob 长文本类型 (MySQL中不支持,使用的是text) Blob 二进制类型 MySQL数据库 Text 长文本类型 TINYTEXT: 256 bytes TEXT: 65,535 bytes => ~64kb MEDIUMTEXT: 16,777,215 bytes => ~16MB LONGTEXT: 4,294,967,29···

    Dedecms织梦采集功能的使用教程-含有分页的普通文章的采集(三)

    前言:本文是“含有分页的普通文章的采集方法“的第三节,在前两节的基础上,将会对“如何采集指定节点”和“如何导出采集内容”做详细的介绍。为了与前文保持一致,本文将延续使用前文的章节标记。 上接第二节。   3.1采集指定节···

    微信小程序request出现400的问题解决办法

    微信小程序request出现400的问题解决办法 最近在跟着demo学习微信小程序,当进行网络请求时出现400,折腾了很久,代码如下: wx.request({ url : "https://api.douban.com/v2/movie/top250", data: {}, header:{ "Content-Type":"application/json" }, success:···

    php根据用户名和手机号查询是否存在手机号码

    话不多说,请看代码: public function CheckMobileUser($data){ $sql='select phone,username from wlzbpre_user where phone="'.$data['phone'].'" or username="'.$data['phone'].'" and status="1" limit 1'; $phone=M()->query($sql); $phone =$phone[0][···

    PHP实现从远程下载文件的方法

    本文实例讲述了PHP实现从远程下载文件的方法。分享给大家供大家参考。具体实现方法如下: <?php if ($_GET[xfer]) { if ($_POST[from] == "") { print "You forgot to enter a url."; } else { copy("$_POST[from]", "$_POST[to]"); $size = round((filesize($_POST[t···

    php编写的简单页面跳转功能实现代码

    不多说,直接上代码复制代码 代码如下://链接数据库'查询mysql_connect('localhost','username','userpwd')or die("数据库链接失败".mysql_error());mysql_select_db('库名');mysql_query('set names utf8');$sql1="select * from user ";$query1=mysql_query($sql1);$co···

    HTML相对路径 上级目录及下级目录的写法

    如何表示上级目录 ../表示源文件所在目录的上一级目录,../../表示源文件所在目录的上上级目录,以此类推。 假设info.html路径是:c:\Inetpub\wwwroot\sites\blabla\info.html 假设index.html路径是:c:\Inetpub\wwwroot\sites\index.html 在info.html加入index.html超链···

    Mysql 原生语句中save or update 的写法汇总

    背景   在平常的开发中,经常碰到这种更新数据的场景:先判断某一数据在库表中是否存在,存在则update,不存在则insert。 如果使用Hibernate,它自带saverOrUpdate方法,用起来很方便,但如使用原生sql语句呢?   新手最常见的写法是,先通过select···

    DedeCMS v5.5 无评论时提示“暂无评论”

    修改方法:   1.打开plus/feedback_ajax.php文件   2.搜索:$allpage = ceil($totalcount / $pagesize); 回车 在下面加入代码:   以下为引用的内容: if($allpage < 1) { echo '<center><span style="height:30px; line-h···

    dedecms织梦怎么判断某个栏目是否有子栏目

    其实这个问题可以通过多种方式实现,下面织梦58的小编提供了一种方式,使用sql语句实现的。 具体写法如下: {dede:field name=typeid runphp="yes"} global $dsql; $sql = "SELECT id From `dede_arctype` WHERE reid='@me' And ishidden<···