前言
在我们开始学习javascript 开始时,学习对象时,知道了,在js中,对象赋值传递的只是对象在内存中的存储地址,并非数据的本身,这种现象,可以说是一种双刃剑,既有趣,又有坑。
在自己开发的过程中,我们有时候,为了方便赋值,默认使用了这种特性,在修改目标对象的同时,连带着修改了源对象。
但是,对于接手开发的小伙伴来说,就比较惨了,找不到数据的赋值,数据莫名的变化了,几行代码的时候还好说,五百行,一千行,甚至上万行的时候,这就变成了兰德里的折磨。
深浅克隆定义
浅克隆
浅克隆,将源对象中的值类型的变量复制一份给目标对象;将源对象中的引用类型的变量地址复制到目标对象中,即源对象与目标对象中引用类型变量地址指向一致;
换句话说,当源对象被克隆时只复制它本身和其中包含的基础类型的成员变量,而引用类型的成员对象的值并没有被克隆,只是赋值了数据的地址指向。
深克隆
深克隆,将源对象中,无论是值类型还是引用类型变量都克隆一份到目标对象中。
换句话说,深克隆会将所有都进行克隆,源对象与目标对象相同,但不存在任何关系。
实现方式
浅克隆
- Object.assign
export const shallowCloneByAssign = function (obj) {
if (typeof obj !== "object" || obj === null) {
return obj; // 非对象直接返回
}
return Object.assign({}, obj);
}
- 扩展运算符
// 方式二 扩展运算符(...)
export const shallowCloneByOpe = function (obj) {
if (typeof obj !== "object" || obj === null) {
return obj; // 非对象直接返回
}
return { ...obj };
}
- 直接遍历复制,如果不用递归元素,遍历一层,效果也是浅克隆。
深克隆
- 利用遍历+递归的方式将源对象的所有元素遍历复制一遍。
// 方式一
export const deepClone = function (obj) {
if (typeof obj !== "object" || obj === null) {
return obj; // 非对象直接返回
}
let copy = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
copy[key] = deepClone(obj[key]);
}
}
return copy;
};
- 利用 json 方式转化复制
// 方式二
export const deepCloneByJSON = function (obj) {
if (typeof obj !== "object" || obj === null) {
return obj; // 非对象直接返回
}
return JSON.parse(JSON.stringify(obj));
};
使用场景
- 关于浅克隆的使用场景,一般赋值就属于浅克隆吧。
- 具体区别深克隆的使用场景,无非就是判断当前场景中,是否要使得前后操作对源数据造成影响:
- 需要保留源数据干净的场景
- 数据状态回退
总结
对于深浅克隆的方式可能还能其他,之后遇见再进行完善,目前,我用到的就是这些,至于说用lodash库,那就不属于探讨的地方了,毕竟直接引入使用即可。
通过学习代码的基础,来完善自己的逻辑思维,坚实基础,才是最重要的吧。
引用当前高中语文老师的一句话就是“基础不牢,地动山摇!”或许放在此刻依旧受用。
愿有所帮助吧,诸君也可多多建议。
参考资源
- 《JavaScript学习指南》
- 《 你不知道的JavaScript》
- 菜鸟教程:https://www.runoob.com/js/js-tutorial.html