关于深拷贝
在做项目时遇到了表单填写后,不点击提交或确定,其数据也发生了变化;
这时候,我们需要使用到深拷贝去解决这个问题:
深拷贝:创建一个新的对象和数组,将原对象的各项属性的"值"(数组的所有元素)拷贝过来,是"值"而不是"引用",新对象跟原对象不共享内存,修改新对象不会影响到原对象。
浅拷贝(Shallow Copy):将原对象的引用复制给新对象,新对象与原对象共享同一个内存地址,修改新对象会影响原对象,反之亦然。浅拷贝只复制了对象的引用,而没有复制对象本身。
解决方法一
将数据库获取数据赋值到一个tempIndex中(非表单中的数据),当点击按钮修改非表单数据时深拷贝tempIndex,赋值到index,在表单中对index做修改,点击确定或提交,把数据发送至后端,这样在没有点击确定或提交时原数据才不会跟着改变。
缺点
仅能用于防止意外修改,未实现深拷贝
解决方法二
function cloneJSON(source) {
return JSON.parse(JSON.stringify(source));
}通过将对象转换为 JSON 字符串,然后再将 JSON 字符串解析为新对象的方式实现深拷贝,适用于大多数简单的对象和数组。
使用
JSON.stringify(source)将源对象(source)序列化为 JSON 字符串。这个过程会将对象的所有属性和值转换为字符串表示。使用
JSON.parse()将 JSON 字符串解析为新的对象。这个过程会创建一个新的对象,其中包含源对象的所有属性和值的拷贝。
缺点
- 无法处理循环引用的对象。如果对象中存在循环引用,
JSON.stringify()会抛出错误。 - 无法拷贝函数、正则表达式、Symbol 类型等特殊对象。这些对象在序列化和解析过程中会丢失。
- 无法保留对象的原型链。新对象的原型链会被重置为
Object.prototype。
解决方法三:递归实现
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
let clone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key]);
}
}
return clone;
}在循环中,函数使用
hasOwnProperty()方法来检查属性是否为obj自身的属性,以避免拷贝原型链上的属性。对于每个属性,函数递归调用
deepClone()函数来拷贝属性的值,并将拷贝后的值赋给clone对应的属性。
能够处理复杂的对象结构,包括嵌套的对象和数组。它会递归地遍历对象的所有属性,并对每个属性进行深拷贝。这样可以确保拷贝后的对象与原始对象完全独立,互不影响。
缺点
仍然无法处理循环引用的对象,因为递归调用会导致无限循环。
无法拷贝函数、正则表达式、Symbol 类型等特殊对象。
解决方法四:使用第三方库
lodash 是一个流行的 JavaScript 工具库,提供了许多实用的功能,包括深拷贝。您可以使用 lodash 的 cloneDeep 函数实现深拷贝:
const _ = require('lodash');
const newObj = _.cloneDeep(oldObj);
Rarrot