深拷贝、浅拷贝、区别?如何实现?

前言

  • 基本数据存储在中(先进后出)
  • 引用数据指针存储在中,数据存储在
  • 深拷贝和浅拷贝是针引用(复杂)数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝

浅拷贝

  • 浅拷贝 基本类型的数据 - 拷贝的就是基本类型的
  • 浅拷贝 引用类型的数据 - 共享内存地址

javaScript中存在浅拷贝的现象有:

  • 使用扩展运算符实现的数组和对象的复制
  • Object.assign(obj1, obj2)
  • Array.prototype.slice() 语法: arr.slice(start, end)
  • Array.prototype.concat() 语法:arr= arr1.concat(arr2, arr3, arr4)
  • lodash 里面的 _.clone

浅拷贝代码实现:

scss 复制代码
function shallowClone(obj) {
    const newObj = {};
    for(let prop in obj) {
        if(obj.hasOwnProperty(prop)){
            // 未判断obj[prop]的数据类型 仅仅拷贝了一层
            newObj[prop] = obj[prop];
        }
    }
    return newObj;
}

深拷贝

深拷贝就是把一个对象,从内存中完整的拷贝出来,从堆内存中开辟了新区域,用来存新对象,并且修改新对象不会影响原对象

常见的深拷贝:

  • _.cloneDeep() 语法: obj2=_.cloneDeep(bj1)
  • jQuery.extend() 语法:obj2 = $.extend(true, {}, obj1)
  • JSON.parse(JSON.stringify())语法:obj2=JSON.parse(JSON.stringify(obj1))
  • 手写递归

1、_.cloneDeep()

ini 复制代码
const _ = require('lodash');
const obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
const obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);// false

2、jQuery.extend()

ini 复制代码
const $ = require('jquery');
const obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
const obj2 = $.extend(true, {}, obj1);
console.log(obj1.b.f === obj2.b.f); // false

3、JSON.parse(JSON.stringify())

javascript 复制代码
const obj2=JSON.parse(JSON.stringify(obj1))

但是这种方式存在弊端,会忽略 undefined symbol 函数

javascript 复制代码
const obj = {
    name: 'A',
    name1: undefined,
    name3: function() {},
    name4: Symbol('A')
}

const obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj2); // {name: "A"}

4、循环递归

javascript 复制代码
// WeakMap是JavaScript中的一种内置数据结构,它是一种特殊的映射(Map),用于存储键值对
// 与普通的Map不同,WeakMap的键必须是对象
function deepClone(obj, hash = new WeakMap()) {
    // 如果是null 或者 undeind 不进行拷贝操作
    if (obj === null) return obj; 
    if (obj instanceof Date) return new Date(obj);
    if (obj instanceof RegExp) return new RegExp(obj);
    // 判断是否是对象,不是对象(普通值或者是函数)不需要拷贝
    if (typeof obj !== "object") return obj;
    // 是对象的话要进行深拷贝
    if (hash.get(obj)) return hash.get(obj);
    let cloneObj = new obj.constructor();
    // 找到的是所属原型上的constructor,而原型上的constructor指向的是当前类本身
    hash.set(obj, cloneObj);
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            // 实现递归拷贝
            cloneObj[key] = deepClone(obj[key], hash);
        }
    }
    return cloneObj;
}

总结

浅拷贝和深拷贝都创建出一个新的对象,但在复制对象属性的时候,行为就不一样。浅拷贝只复制属性指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,修改对象属性会影响原对象。

前提为拷贝类型为引用类型的情况下:

  • 浅拷贝是拷贝一层,属性为对象时,浅拷贝是复制,两个对象指向同一个地址
  • 深拷贝是递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址
相关推荐
南屿im4 分钟前
别再被引用坑了!JavaScript 深浅拷贝全攻略
前端·javascript
想要一辆洒水车15 分钟前
vuex4源码分析学习
前端
sophie旭17 分钟前
一道面试题,开始性能优化之旅(6)-- 异步任务和性能
前端·javascript·性能优化
年少不知有林皇错把梅罗当球王18 分钟前
vue2、vue3中使用pb(Base64编码)
前端
FanetheDivine22 分钟前
常见的AI对话场景和特殊情况
前端·react.js
sophie旭23 分钟前
一道面试题,开始性能优化之旅(5)-- 浏览器和性能
前端·面试·性能优化
lypzcgf31 分钟前
Coze源码分析-资源库-编辑知识库-前端源码-核心组件
前端·知识库·coze·coze源码分析·智能体平台·ai应用平台·agent平台
小墨宝35 分钟前
web前端学习 langchain
前端·学习·langchain
北城以北888839 分钟前
Vue--Vue基础(一)
前端·javascript·vue.js
IT_陈寒1 小时前
Python 3.12新特性实战:5个让你的代码提速30%的性能优化技巧
前端·人工智能·后端