这块应该都有过比较深刻的了解了。今天加深下印象和查漏补缺下。
浅拷贝:
let original = { a: 1, b: { c: 2 } };//这边定一个obj,来供拷贝
let shallowCopy = Object.assign({}, original);// let shallowCopy = { ...original };
创建一个浅拷贝对象拷贝原来的对象
shallowCopy.b.c = 3;
修改对象中的深处项
console.log(original); // 输出:{ a: 1, b: { c: 3 } }
console.log(shallowCopy); // 输出:{ a: 1, b: { c: 3 } }
可以发现原来的对象和你所拷贝的对象的值会一起变化
深拷贝:
// 使用JSON方法(有局限性)
let original = { a: 1, b: { c: 2 } };
let deepCopy = JSON.parse(JSON.stringify(original));deepCopy.b.c = 3;
console.log(original); // 输出:{ a: 1, b: { c: 2 } }
console.log(deepCopy); // 输出:{ a: 1, b: { c: 3 } }也可以使用load库的
// 使用lodash库(需要先安装lodash)
// const _ = require('lodash');
// let deepCopy = _.cloneDeep(original);
可以发现原先的对象不会随着你所拷贝对象的变化而变化
手写一个深拷贝
// 深拷贝
function deepClone(obj, cache = new WeakMap()) {
if (typeof obj !== 'object') return obj
if (obj === null) return obj
if (cache.get(obj)) return cache.get(obj) // 防止循环引用,程序进入死循环
if (obj instanceof Date) return new Date(obj)
if (obj instanceof RegExp) return new RegExp(obj)
// 找到所属原型上的constructor,所属原型上的constructor指向当前对象的构造函数
let cloneObj = new obj.constructor()
cache.set(obj, cloneObj) // 缓存拷贝的对象,用于处理循环引用的情况
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key], cache) // 递归拷贝
}
}
return cloneObj
}
const obj = { name: 'Jack', address: { x: 100, y: 200 } }
obj.a = obj // 循环引用
const newObj = deepClone(obj)
console.log(newObj.address === obj.address) // false
初步解析:
1.首先判断类型,基本类型,直接返回
2.复杂对象判断,处理null的逻辑
3.防止函数陷入无限引用
4.处理日期和正则表达式
这边用一个复杂对象来更好的帮助理解
const complexObj = {number: 123,string: 'Hello',date: new Date(),regex: /abc/gi,array: [1, 2, 3],nested: {boolean: true,nullValue: null,undef: undefined,nestedObj: {a: 1,b: [2, 3]}},circular: null // 将会在稍后设置循环引用
};
首先他一定是个对象,不是null date 正则什么的~
这边直接看到循环函数
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key], cache) // 递归拷贝
}
}
其中hasOwnProperty是检查obj是否直接拥有该key,而不是从原型链继承下来的
返回用deepClone进行深拷贝,会进行cloneObj[number]的赋值,即deepClone()
比如例子的object的第一个key为[number],会进行cloneObj[key]的赋值=deepClone(obj[number],cache),其中obj[number]的值为123,!==objecet,会return 123
就可以cloneObj得到{number:123}
再遍历下一个key string,同理,直到key为nested的时候,检测到为object。会重复上边的势力,实现一个新的一模一样的实例