所谓深浅拷贝,其实都是进行复制,主要区别在于复制出来的新对象和原来的对象是否会相互影响
B复制A,修改A | B 互不影响,为深拷贝
B复制A,修改A | B 互相影响,为浅拷贝
浅拷贝
举个栗子:
let oldObj = [1,2,3,4,5,6]
let newObj = oldObj
newObj[2] = 9
// newObj [1, 2, 9, 4, 5, 6]
// oldObj [1, 2, 9, 4, 5, 6]
再举个栗子:
let oldObj = { a:1, b:'xyz', c:[ 1, 2, 3]}
let newObj = oldObj
oldObj.c[1] = 9
// newObj { a:1, b:'xyz', c:[ 1, 9, 3]}
// oldObj { a:1, b:'xyz', c:[ 1, 9, 3]}
let oldObj1 = { a:1, b:'xyz', c:[ 1, 2, 3]}
let newObj1 = Object.assign(oldObj1)
newObj1.c[2] = 111
// newObj { a:1, b:'xyz', c:[ 1, 2, 111]}
// oldObj { a:1, b:'xyz', c:[ 1, 2, 111]}
可以明显的看出,根据oldObj复制出的newObj变量,在更改时,会互相影响,这就是浅拷贝
深拷贝
举个栗子: 还是上述的栗子
let oldObj = [1,2,3,4,5,6]
let newObj = oldObj.slice()
newObj[3] = 111
// newObj [1, 2, 3, 111, 5, 6]
// oldObj [1, 2, 3, 4, 5, 6]
let oldObj = [1,2,3,4,5,6]
let newObj = oldObj.concat()
newObj[3] = 222
// newObj [1, 2, 3, 222, 5, 6]
// oldObj [1, 2, 3, 4, 5, 6]
上述两个栗子,貌似看似是进行了深拷贝,但这只是假象。当数据结构只有一层时,是进行了深拷贝;但是当数据结构为多层时,最外层是深拷贝,而内层只是拷贝了引用地址
举个栗子:
let oldObj = [1,2,3,4,[1,2,3,4,[1,2,3,4,5]]]
let newObj = oldObj.concat()
newObj[4][4][4] = 5555
oldObj[2] = 2222
// newObj [1,2,3,4,[1,2,3,4,[1,2,3,4,5555]]]
// oldObj [1,2222,3,4,[1,2,3,4,[1,2,3,4,5555]]]
再举个栗子:
let oldObj = { a:1, b:'xyz', c:[ 1, 2, 3]}
let newObj = JSON.parse(JSON.stringify(oldObj))
oldObj.c[2] = 333
// oldObj { a:1, b:'xyz', c:[ 1, 2, 333]}
// newObj { a:1, b:'xyz', c:[ 1, 2, 3]}
上述的栗子,并不是最好的深拷贝方法。如果能将多层数据一层一层的复制,那定是极好的!!!
简化版的递归拷贝 🌰:
1.
function deepClone(obj) {
if (typeof obj !== "object") return;
let newObj = Array.isArray(obj) ? [] : {};
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
newObj[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
}
}
return newObj;
}
let oldObj = [
1,
2,
3,
{
a: "aa",
b: "bb",
func: function() {
let x = 10,
y = 25;
return () => x + y;
},
},
];
let newObj = deepClone(oldObj);
console.log(newObj);
function deepClone(source) {
// 精准判断是对象还是数组
const targetObj = source.constructor === Array ? [] : {};
// 遍历目标
for (let keys in source) {
// 查看是否有指定的属性
if (source.hasOwnProperty(keys)) {
// 如果值是对象,就递归一下(此处并非精准判断类型)
if (source[keys] && typeof source[keys] === "object") {
targetObj[keys] = source[keys].constructor === Array ? [] : {};
targetObj[keys] = deepClone(source[keys]);
} else {
// 如果不是,就直接赋值
targetObj[keys] = source[keys];
}
}
}
return targetObj;
}
欢迎补充 以及 纠正