JS基础:浅拷贝和深拷贝

99 阅读2分钟

前言

浅拷贝和深拷贝往往指的是引用数据类型的值引用的问题,要分清什么是浅拷贝和深拷贝,就得先聊聊 JavaScript 的数据存储方式

数据类型

JavaScript 把数据类型分为两类:基本数据类型引用数据类型

基本数据类型:存放在栈内存上。其中,JS 有 5 个,ES 有 2 个

numberstringbooleannullundefined

ES 引入的数据类型:BigIntSymbol

引用数据类型:是指由类型的实际值引用(类似于指针)表示的数据类型。引用数据类型是存放在堆内存中的对象,变量其实是保存的在栈内存中的一个指针(保存的是堆内存中的引用地址),这个指针指向堆内存对应的对象

ObjectArray
  • 浅拷贝:仅仅分配一个指针指向原对象内存地址

  • 深拷贝:分配一个新指针和新地址

浅拷贝

浅拷贝指的是只拷贝堆地址的引用

var arr = [1,2,3];
var arrs = arr; // 复制
arrs.push(4); // 修改复制
console.log(arr); // [1, 2, 3, 4] arr也发生改变

深拷贝

深拷贝堆是指内存中开辟一块新的空间,把原对象的值复制到新的空间,引用指向新的地址

Object.assign

Object.assign(target, obj)

当对象的层级只有一级时,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性后就是浅拷贝

JSON 转换

JSON.prase(JSON.stringify(obj))

一般使用 try catch 包裹。同时可以通过发送日志的,再使用日志中台统计我们的各种报错原来,来发现我们开发过程中的前端或者后端的不规范,不合理等

问题:会导致对象中包含 functionundefined、正则、时间对象等丢失

递归

function deepClone(){
    const targetObj = obj.constructor === Array ? [] : {}; // 判断复制的目标结果是数组还是对象
    for(let keys in obj){ // 遍历目标
        if(obj.hasOwnProperty(keys)){
            if(obj[keys] && typeof obj[keys] === 'object'){ // 如果值是对象,就递归一下
                res[keys] = obj[keys].constructor === Array ? [] : {};
                res[keys] = deepClone(obj[keys]);
            } else// 如果不是,就直接赋值
                res[keys] = obj[keys];
            }
        }
    }
    return res;
}

问题:对象内存在循环引用会导致递归死循环