参考博文:浅拷贝与深拷贝浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的 - 掘金 (juejin.cn)
基本数据类型
1.栈存放;2.值不可变;3.值比较;4.赋值传值
引用数据类型
1.堆存放,栈存地址;2.值可变;3.地址比较;4.赋值传址
赋值和浅拷贝的区别
对于引用对象而言,赋值是地址指向同一内存,改变的是同一个对象,因此改变基本数据和子对象都会相互影响。浅拷贝则是开辟一个新的内存空间,改变的不是同一个对象,基本数据拷贝到新对象中改变不会相互影响,而子对象是拷贝的地址,所以子对象的改变会相互影响。
浅拷贝和深拷贝的区别
浅拷贝和深拷贝是基于引用数据对象而言的,浅拷贝会拷贝子对象的地址到新对象中,导致原始对象和新拷贝的对象修改子对象数据时会相互影响,而深拷贝则是完整拷贝子对象的数据,使得新旧数据数据完全分离,修改时不会相互影响。
浅拷贝方法
- Object.assign()
- ...展开运算符
- Array.prototype.contact()
- Array.prototype.slice()
- lodash库的_clone方法
深拷贝方法
- JSON.Parse(JSON.Stringify()) -----缺点是正则和函数无法正确拷贝,也会存在循环引用等问题
- 递归手写deepClone方法
1.weakMap处理循环引用
2.处理特殊对象Set、Map、Date、RegExp
3.处理数组对象
// 深拷贝
const _deepClone = (target, map=new WeakMap()) => {
// 如果是基础类型直接返回
if(typeof target !== 'object' || target == null) return target
// 如果map中已存在拷贝的对象则直接返回拷贝对象
if(map.get(target)) return map.get(target)
// 新建一个空的拷贝对象
let cloneTarget = new target.constructor()
// 将拷贝对象存入map中
map.set(target, cloneTarget)
// 日期类型
if (target instanceof Date) return new Date(target);
// 正则类型
if (target instanceof RegExp) return new RegExp(target);
// set类型数据
if(target instanceof Set){
target.forEach((v) => {
cloneTarget.add(_deepClone(v, map))
})
}
// map类型数据
if(target instanceof Map){
target.forEach((v, k) => {
cloneTarget.set(_deepClone(k, map), _deepClone(v, map))
})
}
// Array or Object
for(let key in target){
if(target.hasOwnProperty(key)){
cloneTarget[key] = _deepClone(target[key], map)
}
}
return cloneTarget
}