面试官:写个深浅拷贝吧。 我:…💥(原地爆炸)
什么是深浅拷贝?
对基本类型的拷贝就 是对值复制进行一次拷贝,而对于引用类型来说,拷贝的不是值,而是值的地址,最终两个变量的地址 指向的是同一个值。还是以前的例子: 要想将 obj1 和 obj2 的关系断开,也就是不让他指向同一个地址。根据不同层次的拷贝,分为深拷贝 和浅拷贝。
- 浅拷贝:只进行一层关系的拷贝。
- 深拷贝:进行无限层次的拷贝。
浅拷贝:只考虑对象类型。
function shallowCopy(obj) {
if (typeof obj !== 'object') return obj
let newObj = obj instanceof Array ? [] : {}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key]
}
}
return newObj
}
既然浅拷贝
达不到我们的要求,本着效率的原则,我们找找有没有帮助我们实现深拷贝
的方法。
简单版深拷贝:只考虑普通对象属性,不考虑内置对象和函数。
function deepClone(obj) {
if (typeof obj !== 'object') return;
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key];
}
}
return newObj;
}
复杂版深克隆:基于简单版的基础上,还考虑了内置对象比如 Date、RegExp 等对象和函数以及解决了循环引用的问题。
const isObject = (target) => (typeof target === "object" || typeof target === "function") && target !== null;
function deepClone(target, map = new WeakMap()) {
if (map.get(target)) {
return target;
}
// 获取当前值的构造函数:获取它的类型
let constructor = target.constructor;
// 检测当前对象target是否与正则、日期格式对象匹配
if (/^(RegExp|Date)$/i.test(constructor.name)) {
// 创建一个新的特殊对象(正则类/日期类)的实例
return new constructor(target);
}
if (isObject(target)) {
map.set(target, true); // 为循环引用的对象做标记
const cloneTarget = Array.isArray(target) ? [] : {};
for (let prop in target) {
if (target.hasOwnProperty(prop)) {
cloneTarget[prop] = deepClone(target[prop], map);
}
}
return cloneTarget;
} else {
return target;
}
}
✨✨✨留个三连再走吧,秋梨膏~~