当前位置: 首页 > article >正文

前端 | 浅拷贝深拷贝

在前端开发中,我们经常需要复制对象或数组,但不同的复制方式可能会影响数据的完整性和应用的稳定性。本文将深入探讨浅拷贝(Shallow Copy)和深拷贝(Deep Copy)的区别、实现方式及适用场景。

1. 浅拷贝

1.1 什么是浅拷贝

浅拷贝指的是仅复制对象的第一层属性,而不会复制嵌套对象的引用。如果原对象的某个属性是引用类型(如对象或数组),浅拷贝后,拷贝对象的该属性仍然指向原对象中的引用地址,修改拷贝对象的嵌套属性会影响原对象。

1.2 浅拷贝的实现方式
1)Object.assign()

Object.assign()是ES6中对象的拷贝方法,接受的第一个参数是目标对象,其余参数是源对象,用法:Object.assign(target, source_1, ···),该方法可以实现浅拷贝,也可以实现一维对象的深拷贝。

let target = {a: 1};
let object2 = {b: 2};
let object3 = {c: 3};
Object.assign(target,object2,object3);  
console.log(target);  // {a: 1, b: 2, c: 3}
2)扩展运算符

使用扩展运算符可以在构造字面量对象的时候,进行属性的拷贝。语法:let cloneObj = { ...obj };

let obj1 = {a:1,b:{c:1}}
let obj2 = {...obj1};
obj1.a = 2;
console.log(obj1); //{a:2,b:{c:1}}
console.log(obj2); //{a:1,b:{c:1}}
obj1.b.c = 2;
console.log(obj1); //{a:2,b:{c:2}}
console.log(obj2); //{a:1,b:{c:2}}
3)数组方法实现数组浅拷贝

Array.prototype.slice

  • slice()方法是JavaScript数组的一个方法,这个方法可以从已有数组中返回选定的元素:用法:​array.slice(start, end)​,该方法不会改变原始数组。
  • 该方法有两个参数,两个参数都可选,如果两个参数都不写,就可以实现一个数组的浅拷贝。
let arr = [1,2,3,4];
console.log(arr.slice()); // [1,2,3,4]
console.log(arr.slice() === arr); //false

Array.prototype.concat

  • concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
  • 该方法有两个参数,两个参数都可选,如果两个参数都不写,就可以实现一个数组的浅拷贝。
let arr = [1,2,3,4];
console.log(arr.concat()); // [1,2,3,4]
console.log(arr.concat() === arr); //false
4)手写实现浅拷贝
function shallowCopy(object) {
  if (!object || typeof object !== "object") return;  // 只拷贝对象

  // 根据 object 的类型判断是新建一个数组还是对象
  let newObject = Array.isArray(object) ? [] : {};

  // 遍历 object,并且判断是 object 的属性才拷贝
  for (let key in object) {
    if (object.hasOwnProperty(key)) {
      newObject[key] = object[key];
    }
  }

  return newObject;
}

2. 深拷贝

2.1 什么是深拷贝?

深拷贝指的是创建一个完全独立的副本,拷贝后的对象与原对象互不影响。如果原对象包含嵌套对象,深拷贝会递归复制所有层级的内容,而不是复制引用。

2.2 深拷贝的实现方式
1)JSON方法
  • JSON.parse(JSON.stringify(obj))是目前比较常用的深拷贝方法之一,它的原理就是利用 JSON.stringify 将 js对象序列化(JSON字符串),再使用 JSON.parse来反序列化(还原)js对象。
  • 这个方法可以简单粗暴的实现深拷贝,但是还存在问题,拷贝的对象中如果有函数,undefined,symbol,当使用过 JSON.stringify()进行处理之后,都会消失。
let obj1 = {  a: 0,
              b: {
                 c: 0
                 }
            };
let obj2 = JSON.parse(JSON.stringify(obj1));
obj1.a = 1;
obj1.b.c = 1;
console.log(obj1); // {a: 1, b: {c: 1}}
console.log(obj2); // {a: 0, b: {c: 0}}
2)手写实现深拷贝
// 深拷贝的实现
function deepCopy(object) {
  if (!object || typeof object !== "object") return;

  let newObject = Array.isArray(object) ? [] : {};

  for (let key in object) {
    if (object.hasOwnProperty(key)) {
      newObject[key] =
        typeof object[key] === "object" ? deepCopy(object[key]) : object[key];
    }
  }
  
  return newObject;
}

3. 浅拷贝 vs 深拷贝

特点适用场景
浅拷贝仅复制第一层,引用类型仍然共享适用于对象层级较浅、且不担心数据共享的情况
深拷贝递归复制所有属性,生成全新对象适用于数据完全独立、对象层级较深的情况

http://www.kler.cn/a/533371.html

相关文章:

  • C++资源管理
  • 《深度洞察ICA:人工智能信号处理降维的独特利器》
  • Hive on Spark优化
  • 【Linux系统】信号:再谈OS与内核区、信号捕捉、重入函数与 volatile
  • 昆仑万维Java开发面试题及参考答案
  • 会计学基础
  • chrome插件模板;使用 React 18 和 Webpack 5 的 Chrome 扩展样板
  • 【Linux网络编程】:URL(encode),HTTP协议,telnet工具
  • w193基于Spring Boot的秒杀系统设计与实现
  • 前端导出Excel表格
  • 【Redis_2】短信登录
  • 常用集合的简单总结
  • VSCode编辑前端快速开发模板
  • c++ Base64编码
  • 使用python实现与本地ollama部署的deepseek对话
  • p5r预告信生成器API
  • Windows Docker笔记-安装docker
  • C++ 入门速通-第5章【黑马】
  • iOS 老项目适配 #Preview 预览功能
  • python基础入门:2.1变量与基本数据类型
  • 音频录制一般在什么情况下会选择保存为PCM?什么情况会选择保存为WAV?
  • torchtext.get_tokenizer
  • C32.【C++ Cont】静态实现双向链表及STL库的list
  • 蓝桥杯整数删除(优先队列pair,模拟链表)
  • 今日AI和商界事件(2025-02-05)
  • punkt缺失问题