# 导读
最近经常看到很多JavaScript手写代码的文章总结,里面提供了很多JavaScript Api的手写实现。
里面的题目实现大多类似,而且说实话很多代码在我看来是非常简陋的,如果我作为面试官,看到这样的代码,在我心里是不会合格的,本篇文章我拿最简单的深拷贝来讲一讲。
看本文之前先问自己三个问题:
-
你真的理解什么是深拷贝吗?
-
在面试官眼里,什么样的深拷贝才算合格?
-
什么样的深拷贝能让面试官感到惊艳?
本文由浅入深,带你一步一步实现一个惊艳面试官的深拷贝。
本文测试代码:https://github.com/ConardLi/ConardLi.github.io/tree/master/demo/deepClone
例如:代码clone到本地后,执行 node clone1.test.js查看测试结果。
建议结合测试代码一起阅读效果更佳。
# 深拷贝和浅拷贝的定义
深拷贝已经是一个老生常谈的话题了,也是现在前端面试的高频题目,但是令我吃惊的是有很多同学还没有搞懂深拷贝和浅拷贝的区别和定义。例如前几天给我提issue的同学:

很明显这位同学把拷贝和赋值搞混了,如果你还对赋值、对象在内存中的存储、变量和类型等等有什么疑问,可以看看我这篇文章:https://juejin.im/post/5cec1bcff265da1b8f1aa08f 。
你只要少搞明白拷贝和赋值的区别。
我们来明确一下深拷贝和浅拷贝的定义:
浅拷贝:

创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
深拷贝:

将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象
话不多说,浅拷贝就不再多说,下面我们直入正题:
# 乞丐版
在不使用第三方库的情况下,我们想要深拷贝一个对象,用的最多的就是下面这个方法。
JSON.parse(JSON.stringify());
这种写法非常简单,而且可以应对大部分的应用场景,但是它还是有很大缺陷的,比如拷贝其他引用类型、拷贝函数、循环引用等情况。
显然,面试时你只说出这样的方法是一定不会合格的。
接下来,我们一起来手动实现一个深拷贝方法。
# 基础版本
如果是浅拷贝的话,我们可以很容易写出下面的代码:
function clone(target) {
let cloneTarget = {};
for (const key in target) {
cloneTarget[key] = target[key];
}
return cloneTarget;
};
创建一个新的对象,遍历需要克隆的对象,将需要克隆对象的属性依次添加到新对象上,返回。
如果是深拷贝的话,考虑到我们要拷贝的
