深度理解前端手写代码面试题——深克隆方法详解
2024-01-18 08:18:18
前言
大家好,我是晚天。在前端面试中,手写代码是不可或缺的一部分。常见的手写代码题也基本是可枚举的。网上也有很多面经文章会讲到手写代码,但是大都不够全面、不够深度,有些低质量文章甚至会误导初学者。
本文将深度解析前端面试中的经典手写代码题——深克隆方法,帮助读者全面理解深克隆与浅克隆的区别、深克隆的实现原理及其实现方法,以及如何应对循环引用的问题,从而在面试中脱颖而出。
深克隆与浅克隆
在理解深克隆之前,我们先来了解一下浅克隆。浅克隆只复制对象的属性,而不会复制对象引用的对象。也就是说,浅克隆只复制一层,而深克隆会复制对象的所有层级,包括对象引用的对象。
举个例子,我们有一个对象obj
,其中有一个属性name
,还有一个属性children
,children
是一个数组,其中包含两个对象child1
和child2
。
const obj = {
name: 'obj',
children: [
{ name: 'child1' },
{ name: 'child2' }
]
};
如果我们使用浅克隆来复制obj
,那么新对象obj2
将具有相同的属性和属性值,但是obj2.children
将引用与obj.children
相同的对象。
const obj2 = Object.assign({}, obj);
如果我们修改obj2.children[0].name
,那么obj.children[0].name
也会被修改,因为它们引用的是同一个对象。
obj2.children[0].name = 'child1-modified';
console.log(obj.children[0].name); // 'child1-modified'
如果我们使用深克隆来复制obj
,那么新对象obj3
将具有相同的属性和属性值,但是obj3.children
将引用与obj.children
不同的对象。
const obj3 = JSON.parse(JSON.stringify(obj));
如果我们修改obj3.children[0].name
,那么obj.children[0].name
不会被修改,因为它们引用的是不同的对象。
obj3.children[0].name = 'child1-modified';
console.log(obj.children[0].name); // 'child1'
深克隆的实现原理
深克隆的实现原理很简单,就是将对象的所有属性和属性值都复制一遍,包括对象引用的对象。
我们可以使用递归算法来实现深克隆。首先,我们需要创建一个新的对象newObj
,然后遍历obj
的所有属性,将每个属性的值复制到newObj
中。
function deepClone(obj) {
const newObj = {};
for (const key in obj) {
newObj[key] = obj[key];
}
return newObj;
}
如果obj
的某个属性是一个对象,那么我们需要递归地克隆该对象。
function deepClone(obj) {
const newObj = {};
for (const key in obj) {
if (typeof obj[key] === 'object') {
newObj[key] = deepClone(obj[key]);
} else {
newObj[key] = obj[key];
}
}
return newObj;
}
深克隆的实现方法
我们可以使用多种方法来实现深克隆,包括:
- 使用递归算法
- 使用JSON.parse(JSON.stringify(obj))
- 使用lodash.cloneDeep(obj)
如何应对循环引用
在实现深克隆时,我们需要特别注意循环引用。循环引用是指对象本身或其属性引用了自身。如果我们直接使用递归算法来实现深克隆,那么遇到循环引用时就会陷入死循环。
为了应对循环引用,我们可以使用哈希表来存储已经克隆过的对象。当我们遇到一个对象时,我们首先检查哈希表中是否已经存在该对象。如果存在,那么我们直接返回哈希表中存储的克隆对象。如果不存在,那么我们克隆该对象,并将其存储在哈希表中。
function deepClone(obj, hash = new Map()) {
const newObj = {};
for (const key in obj) {
if (typeof obj[key] === 'object' && obj[key] !== null) {
if (hash.has(obj[key])) {
newObj[key] = hash.get(obj[key]);
} else {
hash.set(obj[key], newObj);
newObj[key] = deepClone(obj[key], hash);
}
} else {
newObj[key] = obj[key];
}
}
return newObj;
}
结语
深克隆是前端面试中常见的手写代码题之一。通过本文的讲解,希望读者能够全面理解深克隆与浅克隆的区别、深克隆的实现原理及其实现方法,以及如何应对循环引用的问题。
在实际面试中,面试官可能会要求你手写深克隆代码,并可能给你一些特殊场景,比如存在循环引用等。因此,在准备面试时,除了掌握基本原理和实现方法外,还需要多做一些练习,才能在面试中游刃有余。