基本数据类型
基本数据类型存放在栈内存中,拷贝之后都是相互独立的,无所谓深浅。
引用数据类型
浅拷贝和深拷贝讨论是引用数据类型,即为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