JavaScript深浅拷贝,其实没那么难!

简介: JavaScript深浅拷贝,其实没那么难!

正文


什么是深浅拷贝?


  • 浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
  • 深拷贝:将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象


浅拷贝的几种方式


array.slice()array.concat()Object.assign() 都能实现浅拷贝,前两个针对数组。还可以用以下这种方式。

// 浅拷贝
function shallowCopy(source, target = {}) {
  for (let key in source) {
    if(source.hasOwnProperty(key)) {
      target[key] = source[key]
    }
  }
  return target;
}
let student1 = {
  name: "Frankie",
  age: 22,
  language: ["Chinese", ["English", "German"]]
};
let student2 = shallowCopy(student1);
student2.language[1] = ["French"];
console.log(student1);
console.log(student2);
// 打印对比可知,language 同时改变了


深拷贝的几种方式


  • JSON


利用  JSON.stringify & JSON.parse 方法

不足:

  1. 无法拷贝对象中的方法属性;
  2. 无法拷贝对象中的 undefined 属性


  • JQuery


JQuery 提供的两种方法 $.extend()$.clone() ,前者是 JS 对象的拷贝、后者是 DOM 对象的拷贝(这里不讨论)


不足:

  1. 需要引入 JQuery 库
  2. 无法拷贝对象中的 undefined 属性


  • 递归


利用 for..in..hasOwnProperty递归实现

不足:比上面的两种方式稍复杂


递归实现深拷贝

// 假设在 Object 的原型,添加一个 height 属性
Object.prototype.height = 180;
// student1 什么类型的属性都有了
let student1 = {
  name: "Frankie",
  age: 22,
  private: true,
  friends: ["Mandy", "John"],
  abilities: undefined,
  other: null,
  car: {
    color: "gray",
    brand: "Benz"
  },
  teacher: {
    name: "Ada",
    student: ["Helkai", "Jerry"]
  },
  learn: function() {
    console.log(this.name + " is learning JavaScript now.");
  },
};
// 深拷贝
function deepCopy(source, target = {}) {
  for (let key in source) {
    // for...in... 会遍历原型链上的属性,所以这里需要利用 hasOwnProperty 判断,否则会把 Object 原型上的 height 也拷贝进去了
    if (source.hasOwnProperty(key)) {
      if (typeof source[key] === "object" && source[key] !== null) {
        // 判断是否为数组
        target[key] = Object.prototype.toString.call(source[key]) === "[object Array]" ? [] : {};
        // 递归
        deepCopy(source[key], target[key]);
      } else {
        target[key] = source[key];
      }
    }
  }
  return target;
}
// 从 student1 中拷贝一个 student2 出来
let student2 = deepCopy(student1);
// 修改 student2 的属性值
student2.name = "Steven";
student2.age = 20;
student2.car = {
  color: "red",
  brand: "BMW"
};
student2.friends[1] = "Jone";
student2.teacher.age = "30";
// 打印结果看下面截图,结果是没有相互影响的
console.log(student1);
console.log(student2);
// JSON 方式
let student3 = JSON.parse(JSON.stringify(student1));
console.log(student3);  //  打印 student3 可见 abilities、learn 属性丢失了


运行结果


77.webp.jpg

日常搬砖选择哪种方式呢,视具体情况而定。我的话,能用 JSON 方式解决的,绝不用递归,没必要复杂化,简单够用即可。但是学习的话,递归的方式必须得懂啊,其实不难懂。

其实还有优化的空间,我们都知道 for...in... 的性能是比较差的。关于性能优化篇,可以看下掘金某大神的文章,这里


The end.


目录
相关文章
|
6月前
|
JSON JavaScript 前端开发
JavaScript 中更现代的深拷贝方法!
JavaScript 中更现代的深拷贝方法!
131 0
|
5月前
|
JSON JavaScript 前端开发
【JavaScript】JavaScript中的深拷贝与浅拷贝详解:基础概念与区别
JavaScript 中,理解数据拷贝的深浅至关重要。浅拷贝(如扩展运算符`...`、`Object.assign()`)仅复制对象第一层,共享内部引用,导致修改时产生意外联动。深拷贝(如自定义递归函数、`_.cloneDeep`或`JSON.parse(JSON.stringify())`)创建独立副本,确保数据隔离。选择哪种取决于性能、数据独立性和资源需求。深拷贝虽慢,但确保安全;浅拷贝快,但需小心引用共享。在面试中,理解这些概念及其应用场景是关键。
127 4
【JavaScript】JavaScript中的深拷贝与浅拷贝详解:基础概念与区别
|
5月前
|
JavaScript 前端开发 安全
深入探索JavaScript中的structuredClone:现代深拷贝的解密指南
深入探索JavaScript中的structuredClone:现代深拷贝的解密指南
46 0
|
JSON JavaScript 前端开发
超详细的JavaScript深拷贝实现
超详细的JavaScript深拷贝实现
252 0
超详细的JavaScript深拷贝实现
|
JSON JavaScript 前端开发
JavaScript深拷贝,看这一篇就够啦!
最近面试的时候被问到了深拷贝,我自信满满的写出了使用JSON的快捷方法,与递归深拷贝方法(只写了基础版的拷贝对象)。🤡然后...
4084 0
|
存储 JSON JavaScript
《现代Javascript高级教程》JavaScript深拷贝与浅拷贝
JavaScript深拷贝与浅拷贝 引言 在JavaScript中,对象的拷贝是一项常见的操作。浅拷贝和深拷贝是两种常用的拷贝方式。浅拷贝只复制对象的引用,而深拷贝创建了一个全新的对象,包含与原始对象相同的值和结构。深拷贝和浅拷贝各有适用的场景和注意事项。本文将详细介绍如何实现一个完整而优雅的深拷贝函数,处理循环引用和特殊类型,优化性能,并探讨深拷贝和浅拷贝的应用场景、注意事项和相关属性。
89 0
|
JavaScript 前端开发
JavaScript的深浅拷贝
JavaScript的深浅拷贝
81 0
|
JavaScript 前端开发
|
JavaScript 前端开发 索引
《JavaScript高级程序设计》__ 基本引用类型(上)
前言 大家好,我是HoMeTown,web领域有一本神书大家应该都有看过,这本书我看过两遍,但是每次看都是粗粗的略过一些重要的知识点,甚至一些面试过程中的问题,在这本书里都能找到答案。
109 0
|
JavaScript 前端开发 程序员
一篇文章带你搞懂JavaScript原型对象
一篇文章带你搞懂JavaScript原型对象
183 0
一篇文章带你搞懂JavaScript原型对象