js数组浅拷贝_js数组深度复制

js数组浅拷贝_js数组深度复制JavaScript实现数组的深拷贝、浅拷贝vararr=[‘old’,1,true,null,undefined];varnew_arr=arr.concat();//或者varnew_arr=arr.slice()也是一样的效果;new_arr[0]=’new’;console.log(arr);//["ol……

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

浅拷贝:创建一个新的对象,来接受重新复制或引用的对象值。如果对象属性是基本的数据类型,复制的就是基本类型的值给新对象;但如果属性是引用数据类型,复制的就是内存中的地址,如果其中一个对象改变了这个内存中的地址,会影响到另一个对象,因为两者共同指向同一个地址。

数组的浅拷贝
可用concat、slice返回一个新数组的特性来实现拷贝

var arr = ['old', 1, true, null, undefined];
var new_arr = arr.concat(); // 或者var new_arr = arr.slice()也是一样的效果;
new_arr[0] = 'new';
console.log(arr); // ["old", 1, true, null, undefined]
console.log(new_arr); // ["new", 1, true, null, undefined]

浅拷贝,还可以用Object.assign()方法实现

let target = { 
   };
let source = { 
    a: { 
    b: 2 } };
Object.assign(target, source);
console.log(target); // { a: { b: 10 } }; 
source.a.b = 10; 
console.log(source); // { a: { b: 10 } }; 
console.log(target); // { a: { b: 10 } };

但是如果数组嵌套了对象或者数组的话用concat、slice拷贝只要有修改会引起新旧数组都一起改变了,比如:

var arr = [{ 
   old: 'old'}, ['old']];
var new_arr = arr.concat();
arr[0].old = 'new';
new_arr[1][0] = 'new';
console.log(arr); // [{old: 'new'}, ['new']]
console.log(new_arr); // [{old: 'new'}, ['new']]

下面是浅拷贝一个通用方法,实现思路:遍历对象,把属性和属性值都放在一个新的对象里

var shallowCopy = function (obj) { 
   
  // 只拷贝对象
  if (typeof obj !== 'object') return;
  // 根据obj的类型判断是新建一个数组还是一个对象
  var newObj = Array.isArray(obj) ? [] : { 
   };
  // 遍历obj,并且判断是obj的属性才拷贝
  for (var key in obj) { 
   
    if (obj.hasOwnProperty(key)) { 
   
      newObj[key] = obj[key];
    }
  }
  return newObj;
}

// 如果数组元素是基本类型,就会拷贝一份,互不影响,而如果是对象或者数组,就会只拷贝对象和数组的引用,这样我们无论在新旧数组进行了修改,两者都会发生变化。这种叫浅拷贝
// 深拷贝就是指完全的拷贝一个对象,即使嵌套了对象,两者也相互分离,修改一个对象的属性,也不会影响另一个。

数组的深拷贝
方法一:JSON.stringify()不仅可拷贝数组还能拷贝对象(但不能拷贝函数,也不能解决循环引用问题)

var arr = ['old', 1, true, ['old1', 'old2'], { 
   old: 1}]
var new_arr = JSON.parse(JSON.stringify(arr))
console.log(new_arr);

方法二:递归。下面是深拷贝一个通用方法,实现思路:拷贝的时候判断属性值的类型,如果是对象,继续递归调用深拷贝函数

var deepCopy = function(target) { 
   
  // 只拷贝对象
  if (typeof target !== 'object') return target;
  // 根据obj的类型判断是新建一个数组还是一个对象
  var result = Array.isArray(obj) ? [] : { 
   };
  for (var key in target) { 
   
    // 遍历obj,并且判断是obj的属性才拷贝(不能拷贝原型对象的属性)
    if (target.hasOwnProperty(key)) { 
   
      // 判断属性值的类型,如果是对象递归调用深拷贝
      result[key] = typeof target[key] === 'object' ? deepCopy(target[key]) : target[key];
    }
  }
  return result;
}

其中上述方法一、方法二都解决不了循环引用的问题。
方法三,结合map(将方法二的递归改造,解决循环引用问题):

var deepCopy = function (target, map = new Map()) { 
   
  // 只拷贝对象
  if (typeof target !== "object") return target;
  // 克隆数据之前,先判断之前是否有克隆过(解决循环引用的问题)
  let cache = map.get(target);
  if (cache) { 
   
    return cache;
  }
  // 根据obj的类型判断是新建一个数组还是一个对象
  var result = Array.isArray(target) ? [] : { 
   };
  // 将新的结果存到容器中
  map.set(target, result);
  for (var key in target) { 
   
    // 遍历obj,并且判断是obj的属性才拷贝(不能拷贝原型对象的属性)
    if (target.hasOwnProperty(key)) { 
   
      // 判断属性值的类型,如果是对象递归调用深拷贝
      result[key] =
        typeof target[key] === "object"
          ? deepCopy(target[key], map)
          : target[key];
    }
  }
  return result;
};

// 测试代码
let obj = { 
    a: 1, b: [6, 8], c: { 
    e: 3 } };
obj.b.push(obj.c);
obj.c.h = obj.b;
let obj1 = deepCopy(obj);
console.log(obj);
console.log(obj1);
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/187063.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 看完这篇Kafka,你也许就会了Kafka[通俗易懂]

    看完这篇Kafka,你也许就会了Kafka[通俗易懂]Kafka学习文章目录Kafka学习1.Kafka简介1.1Kafka消费模式1.2Kafka的基础架构1.3Kafka的安装和使用2.Kafka高级2.1工作流程2.2文件存储2.3生产者分区策略2.4生产者ISR2.4.1副本数据同步策略2.4.2ISR(同步副本集)2.5生产者ack机制2.6数据一致性问题2.7ExactlyOnce3.消费者分区分配策略3.1分区分配策略3.2消费者offset的存储3.3消费者组案例4.高效读写&Zookeeper作

    2022年5月9日
    35
  • IDEA中Maven依赖下载失败解决方案[通俗易懂]

    使用IDEA进行Maven项目开发时,时不时会遇到pom.xml报错的情况,其中很大概率是因为Maven依赖的jar包下载失败,找来找去也没有找到是什么问题,困扰了很多程序猿,这里给出IDEA中Maven依赖下载失败解决方案,给大家参考,实测有用。首先检查网络有没有问题,确定网络没有问题,请看下一步多次点击重新导入Maven依赖的按钮重新导入Maven依赖有两种方式,如上图所示。如果多…

    2022年4月16日
    123
  • 操作系统:银行家算法(C语言代码)详解

    操作系统:银行家算法(C语言代码)详解银行家算法流程图:银行家算法自然语言描述:设Requesti是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查:(1)如果Requesti[j]≤Need[i,j],便转向步骤2;否则认为出错,因为它所需要的资源数已超过它所宣布的最大值。(2)如果Requesti[j]≤Available[j],便转向步骤3;否则,表示尚无足够资源,Pi须等待。(3)系统试探着把资源分配给进程Pi,并修改下面数据..

    2022年6月13日
    27
  • 2、wxWidgets介绍–菜单栏、状态栏、图标简介

    2、wxWidgets介绍–菜单栏、状态栏、图标简介wxWidgetswxWidgets是一个用来编写C++程序的GUI(图形用户界面)工具包。它是一个开源的、成熟的、跨平台的工具包。wxWidgets应用程序能在所有主流的操作系统上运行,Windo

    2022年7月2日
    23
  • Python多行注释/取消注释快捷键

    Python多行注释/取消注释快捷键step1:选中需要注释/取消注释的所有代码step2:按快捷键系统快捷键Maccommand+/WindowsCtrl+/

    2022年10月26日
    0
  • DAUM WEBTOON_web host

    DAUM WEBTOON_web hostAnnA.[9:07:33PM]:ThankyouforcontactingtheSalesTeam.PleasegivemeamomentwhileIreviewyourquestion.buyspace[9:07:33PM]:buyspace[9:07:51PM]:HelloAnnA.[9:08:01PM]:Hi!…

    2022年10月8日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号