详解JS深拷贝与浅拷贝

详解JS深拷贝与浅拷贝

一、什么是拷贝

在JavaScript中,我们经常需要对一个数据进行拷贝,这里的拷贝指的是将一个数据重新复制一份,从而在新的数据上进行操作,而原始数据不会受到影响。拷贝手段分为两种:浅拷贝和深拷贝。

1.1 浅拷贝

浅拷贝就是将原始数据的引用复制一份给新的数据,这样新数据和原始数据指向同一块内存区域,因此对新数据进行操作,也会影响原始数据。

示例代码:

let obj = {a: 1, b: {c: 2}};
let newObj = obj;
newObj.a = 3;
newObj.b.c = 4;
console.log(obj); // {a: 3, b: {c: 4}}

可以看到,对 newObj 进行操作,同时也影响了 obj

1.2 深拷贝

深拷贝是将原始数据完整地复制一份给新的数据,新数据和原始数据没有任何联系,对新数据的操作也不会影响原始数据。

示例代码:

let obj = {a: 1, b: {c: 2}};
let newObj = JSON.parse(JSON.stringify(obj));
newObj.a = 3;
newObj.b.c = 4;
console.log(obj); // {a: 1, b: {c: 2}}
console.log(newObj); // {a: 3, b: {c: 4}}

可以看到,对 newObj 进行操作,并不影响 obj

二、浅拷贝的实现方法

2.1 Object.assign()

Object.assign()方法将所有的可枚举属性的值从一个或多个源对象复制到目标对象。它会先创建一个新对象,然后将源对象的属性拷贝到新对象上。

示例代码:

let obj1 = {a: 1,b: {c: 2}};
let obj2 = Object.assign({}, obj1);
obj2.a = 3;
obj2.b.c = 4;
console.log(obj1); // {a: 1, b: {c: 4}}
console.log(obj2); // {a: 3, b: {c: 4}}

可以看到,对 obj2 进行操作,并不影响 obj1

2.2 扩展运算符 ...

扩展运算符 ... 也可以实现浅拷贝。它能够将一个数组或对象展开成一系列参数,方便地将其插入一个函数或对象字面量中。

示例代码:

let obj1 = {a: 1,b: {c: 2}};
let obj2 = {...obj1};
obj2.a = 3;
obj2.b.c = 4;
console.log(obj1); // {a: 1, b: {c: 4}}
console.log(obj2); // {a: 3, b: {c: 4}}

可以看到,对 obj2 进行操作,并不影响 obj1

三、深拷贝的实现方法

3.1 手写递归函数

手写递归函数可以非常方便地实现深拷贝,它会遍历对象的所有属性和子属性,并将其转化为一个新的对象返回。

示例代码:

function deepClone(obj) {
  let newObj = Array.isArray(obj) ? [] : {};
  if (obj && typeof obj === "object") {
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        newObj[key] = deepClone(obj[key]);
      }
    }
  }
  else {
    newObj = obj;
  }
  return newObj;
}

let obj1 = {a: 1,b: {c: 2}};
let obj2 = deepClone(obj1);
obj2.a = 3;
obj2.b.c = 4;
console.log(obj1); // {a: 1, b: {c: 2}}
console.log(obj2); // {a: 3, b: {c: 4}}

可以看到,对 obj2 进行操作,并不影响 obj1

3.2 使用第三方包

第三方包 lodash 中的 _.cloneDeep() 方法也可以实现深拷贝。这个方法可以递归地复制一个 JavaScript 对象。

示例代码:

const _ = require('lodash');

let obj1 = {a: 1,b: {c: 2}};
let obj2 = _.cloneDeep(obj1);
obj2.a = 3;
obj2.b.c = 4;
console.log(obj1); // {a: 1, b: {c: 2}}
console.log(obj2); // {a: 3, b: {c: 4}}

可以看到,对 obj2 进行操作,并不影响 obj1

四、深度递归拷贝的注意事项

在深度递归拷贝中,需要注意以下几点:

  1. 对 Date、RegExp、Function 等对象无法进行深拷贝,需要特殊处理。
  2. 对于对象的循环引用,需要避免死循环。

五、总结

浅拷贝只是复制了一个对象的引用,而深拷贝则是复制了整个对象。使用递归函数实现深拷贝时,需要考虑到各种对象类型的情况。如果对数据的操作需要保证原始数据的不变性,建议使用深拷贝。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解JS深拷贝与浅拷贝 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • 原生JS实现图片无缝滚动方法(附带封装的运动框架)

    下面是对“原生JS实现图片无缝滚动方法(附带封装的运动框架)”的完整攻略。 1. 实现图片无缝滚动的基本思路 实现图片无缝滚动,是需要对图片进行滚动并将其无限循环的。具体的实现思路如下: 创建一个容器,设置其宽度为图片的总宽度。 手动复制一份图片,将其添加到容器的最后。 定时器每次移动容器的left值,实现滚动效果。 当容器的left值达到任何一张图片的边界…

    JavaScript 2023年6月11日
    00
  • javascript 无提示关闭窗口脚本

    标题:如何编写 Javascript 无提示关闭窗口脚本 正文: 如果你需要在网页中编写一个 JavaScript 无提示关闭窗口脚本,可以按照以下步骤进行操作: 一、创建一个 JavaScript 函数 首先,你需要创建一个 JavaScript 函数来关闭窗口。这个函数可以使用 window.close() 方法来关闭当前窗口。请注意,这种方式会直接关闭…

    JavaScript 2023年6月11日
    00
  • 浅谈js中字符和数组一些基本算法题

    下面我将为您详细讲解“浅谈js中字符和数组一些基本算法题”的完整攻略。 确定字符串中的唯一字符 题目描述 给定一个字符串,编写一个函数来确定它是否是该字符串的某个字符的排列之一。例如,输入“abc”和“cba”,你应该返回true,但是如果输入“abc”和“def”,则应按false。 解决方案 一个字符串是另一个字符串的排列之一,意味着它们都由相同的字符组…

    JavaScript 2023年5月28日
    00
  • javascript模拟实现计算器

    为了让大家更好地理解,我先解释一下什么是JavaScript模拟实现计算器,然后再提供完整攻略。 JavaScript模拟实现计算器,是指使用JavaScript语言来模拟实现一个计算器的功能,可以通过输入数字、运算符和特殊符号等来进行基本的数学运算,如加、减、乘、除以及求余数等。 现在来说一下实现这个功能的具体攻略: HTML 部分 首先在 HTML 中创…

    JavaScript 2023年5月27日
    00
  • JS实现unicode和UTF-8之间的互相转换互转

    JS实现unicode和UTF-8之间的互相转换,需要借助一些内置的函数和方法来完成。下面给出一些示例来说明具体的实现方法。 1. Unicode转UTF-8 Unicode是一种宽字符集,而UTF-8是一种字节编码方式,它们之间需要做转换。下面的代码演示了如何将一个Unicode字符串转换成UTF-8格式的字节: function unicodeToUtf…

    JavaScript 2023年5月19日
    00
  • 利用JS hash制作单页Web应用的方法详解

    下面是“利用JS hash制作单页Web应用的方法详解”的完整攻略。 首先介绍什么是单页Web应用 单页Web应用(Single-Page Application,SPA)是一种新型的Web应用程序模型。所谓单页应用,就是将多个页面应用整合在一个HTML文件中,通过JS动态更新HTML内容。 相对于传统的多页应用程序,单页应用程序具有以下优点: 用户体验好,…

    JavaScript 2023年6月11日
    00
  • 简单漂亮的js弹窗可自由拖拽且兼容大部分浏览器

    实现一个简单漂亮的 js 弹窗并让其可自由拖拽需要以下步骤: 确定弹窗的外观和属性,如弹窗大小、标题、内容等。可以使用 HTML 和 CSS 来实现。 示例代码: <div id="popup"> <h3 class="title">弹窗标题</h3> <p class=&qu…

    JavaScript 2023年6月11日
    00
  • Angular.js中window.onload(),$(document).ready()的写法浅析

    Angular.js在页面加载和渲染完成后,可以使用一些方法来操作DOM元素,例如window.onload()和$(document).ready()。但是在Angular.js中,推荐使用指令来操作DOM元素。本文将分别对window.onload()和$(document).ready()以及指令的使用进行讲解。 window.onload()的用法 …

    JavaScript 2023年6月10日
    00
合作推广
合作推广
分享本页
返回顶部