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)
上一篇 2022年10月1日 下午4:46
下一篇 2022年10月1日 下午4:46


相关推荐

  • 迭代阈值法

    迭代阈值法通过迭代方法选择阈值 计算方法如下 1 选择灰度图的平均值作为初始阈值 T0 2 计算小于等于 T0 的平均值 T1 和大于 T0 的平均值 T2 3 新的阈值为 T T1 T2 2 4 比较 T 和 T0 若相等 则返回 T 即为迭代阈值 否则 T0 T 重复 1 3

    2026年3月26日
    2
  • MIUI解BL锁失败[通俗易懂]

    MIUI解BL锁失败[通俗易懂]最后解决办法是:换USB2.0接口分析问题:或许可能是软件兼容性不好,USB3.0影响读取设备信息,导致无法解锁。

    2022年5月27日
    87
  • 上delloc 无呼叫 故障排除 笔记[通俗易懂]

    上delloc 无呼叫 故障排除 笔记

    2022年1月17日
    44
  • Flash基础教程

    Flash基础教程关于 ActionScript nbsp ActionScript 开发过程 nbsp ActionScript 语言及其语法 nbsp ActionScript 中面向对象的编程 nbsp 处理事件 nbsp 显示编程 nbsp 使用绘图 API nbsp 处理位图 nbsp 网络与通信 nbsp nbsp http help adobe com zh CN ActionScr

    2026年3月26日
    2
  • Imagenet数据集_mnist数据集介绍

    Imagenet数据集_mnist数据集介绍官网:http://www.image-net.org/数据集下载地址:http://www.image-net.org/challenges/LSVRC/IMAGENETLargeScaleVisualRecognitionChallenge(ILSVRC)1.基本介绍从2010年开始,每年举办的ILSVRC图像分类和目标检测大赛。Imagenet数据集是目前…

    2022年8月30日
    5
  • BigDecimal转double转换遇到的问题

    BigDecimal转double转换遇到的问题解决科学计数法问题 当 Bigdecimal 类型值为 0 00006 时转成 Double 会变成科学计数法 取消科学计数法 publicString Doubleprinci NumberFormat NumberFormat getInstance 设置保留多少位小数 nf setMaximumFr 6 取消科学计数法 nf setGroupingU false returnnf f

    2026年3月19日
    2

发表回复

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

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