区别JavaScript的浅拷贝和深拷贝并掌握两者的实现方法

基本数据类型

基本数据类型存放在栈内存中,拷贝之后都是相互独立的,无所谓深浅。

引用数据类型

浅拷贝和深拷贝讨论是引用数据类型,即为object类型的数据。

浅拷贝和深拷贝的本质区别

深拷贝和浅拷贝的最根本的区别是否获得了一个对象的复制实体,而不是引用,不是指针。深拷贝在计算机中开辟了一块内存地址用于存放复制的对象;而浅拷贝只是复制了指向被拷贝对象的内存地址,是一个指针,如果源地址对象的对象被改变了,那么浅拷贝出来的对象也会改变。

注意:拷贝有一些属性是拷贝不了的,比如:正则表达式,function,undefined,null,symbol

浅拷贝和深拷贝与等号赋值区别(针对引用类型)
let obj = {
    
    
	name:'小小',
	arr:[1,{
    
    num:2},3]
}
等号赋值

赋值的是该对象的在堆中的地址,而不是在堆中的数据。两个对象指向同一个存储空间,是联动的。

let obj1 = obj;
obj1.name = "大大"; //影响原来的基本类型
obj1.arr[1].num = 123; //影响原来的数组
console.log('obj',obj) //{name:'大大',arr:[1,{num:123},3]}
console.log('obj1',obj1) //{name:'大大',arr:[1,{num:123},3]}
浅拷贝

重新在堆中创建内存,拷贝前后对象的基本类型互不影响,引用数据类型共用同一块内存,是联动的。

let obj2 = Object.assign({
    
    },obj); //实现浅拷贝
obj2.name = "大大小小"; //不影响原来的基本类型
obj2.arr[0] = 'haha'; //影响原来的数组
console.log('obj',obj); //{name:'小小',arr:['haha',{num:123},3]}
console.log('obj2',obj2); //{name:'大大小小',arr:['haha',{num:123},3]}
深拷贝
let obj3 = JOSN.parse(JSON.stringify(obj))
obj3.name = "小小大大"; //不影响原来的基本类型
obj3.arr[1].num = "kakka"; //不影响原来的引用类型
console.log('obj',obj); //{name:'大大',arr:[1,{num:2},3]}
console.log('obj3',obj3); //{name:'小小大大',arr:[1,{num:kakka},3]}
浅拷贝的实现方法
Object.assign()

将任意多个源对象自身可枚举的对象拷贝给目标对象,返回目标对象

let copyObj = Object.assign({
    
    },obj)
函数库lodash的clone方法
let _ = require('lodash')
let copyObj = _.clone(obj)
扩展运算符

与Object.assign()功能相同,是ES 6的一个新特性

let copyObj = {
    
    ...obj}
Array.prototype.concat()–第一层是数组
let copyArr = arr.concat()
Array.prototype.slice()–第一层是数组
let copyArr = arr.slice()
手写函数实现
function shallowClone(obj){
    
    
    let target = {
    
    };
    for(prop in obj){
    
    
        if(obj.hasOwnProperty(prop)){
    
    
            target[prop] = obj[prop]
        }
    }
    return target
}
深拷贝的实现方法
JSON.parse(JSON.stringify())

使用这个方法拷贝对象,正则变成空对象,值为函数、undefined、Symbol的属性会丢失,无法复制。

let deepCopyObj = JSON.parse(JSON.stringify(obj))
函数库lodash的cloneDeep方法
let _ = require('lodash')
let deepCopyObj = _.cloneDeep(obj)
jQuery.extend()方法
let $ = require('jquery')
let deepCopyObj = $.extend(true,{
    
    },obj)
手写函数递归实现

实现思路:

1、判断被拷贝对象,实现对值为Reg Exp、Date、null、undefined、function执行判断,返回对应的值

2、遍历对象,实现深拷贝

function deepClone(obj){
    
    
	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
    let target = new obj.constructor()
    for(let prop in obj){
    
    
        if(obj.hasOwnProperty(prop)){
    
    
            target[prop] = deepClone(obj[prop])
        }
    }
    return target
}

参考链接

https://juejin.cn/post/6844904197595332622#heading-12

おすすめ

転載: blog.csdn.net/weixin_42060560/article/details/110085198