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

前言

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

浅拷贝

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

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;
}

总结

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

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

  • 浅拷贝是拷贝一层,属性为对象时,浅拷贝是复制,两个对象指向同一个地址
  • 深拷贝是递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址
相关推荐
行云&流水16 分钟前
Vue3 Lifecycle Hooks
前端·javascript·vue.js
Sally璐璐23 分钟前
零基础学HTML和CSS:网页设计入门
前端·css
老虎062731 分钟前
JavaWeb(苍穹外卖)--学习笔记04(前端:HTML,CSS,JavaScript)
前端·javascript·css·笔记·学习·html
灿灿121381 小时前
CSS 文字浮雕效果:巧用 text-shadow 实现 3D 立体文字
前端·css
烛阴1 小时前
Babel 完全上手指南:从零开始解锁现代 JavaScript 开发的超能力!
前端·javascript
AntBlack1 小时前
拖了五个月 ,不当韭菜体验版算是正式发布了
前端·后端·python
31535669131 小时前
一个简单的脚本,让pdf开启夜间模式
前端·后端
尘心cx1 小时前
前端-CSS-day1
前端·css
知否技术2 小时前
前端常说的 SCSS是个啥玩意?一篇文章给你讲的明明白白!
前端·scss
CN-Dust2 小时前
[FMZ][JS]第一个回测程序--让时间轴跑起来
javascript