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

前言

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

浅拷贝

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

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

总结

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

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

  • 浅拷贝是拷贝一层,属性为对象时,浅拷贝是复制,两个对象指向同一个地址
  • 深拷贝是递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址
相关推荐
灵感__idea2 小时前
Hello 算法:贪心的世界
前端·javascript·算法
GreenTea3 小时前
一文搞懂Harness Engineering与Meta-Harness
前端·人工智能·后端
killerbasd5 小时前
牧苏苏传 我不装了 4/7
前端·javascript·vue.js
吴声子夜歌5 小时前
ES6——二进制数组详解
前端·ecmascript·es6
码事漫谈5 小时前
手把手带你部署本地模型,让你Token自由(小白专属)
前端·后端
ZC跨境爬虫5 小时前
【爬虫实战对比】Requests vs Scrapy 笔趣阁小说爬虫,从单线程到高效并发的全方位升级
前端·爬虫·scrapy·html
爱上好庆祝5 小时前
svg图片
前端·css·学习·html·css3
橘子编程6 小时前
JavaScript与TypeScript终极指南
javascript·ubuntu·typescript
王夏奇6 小时前
python中的__all__ 具体用法
java·前端·python
叫我一声阿雷吧6 小时前
JS 入门通关手册(45):浏览器渲染原理与重绘重排(性能优化核心,面试必考
javascript·前端面试·前端性能优化·浏览器渲染·浏览器渲染原理,重排重绘·reflow·repaint