手写实现一个深拷贝是面试题经常会考到的,但是很多人可能考虑不全面,今天我们就来逐步实现一个考虑全面的深拷贝.
深拷贝和浅拷贝的区别?
浅拷贝:将内存中的某个对象复制一份,在内存中开辟一块新的空间,如果复制的这个对象的属性为基本数据类型
,则拷贝的便为这个值本身,如果为复杂数据类型,则拷贝复制的为地址,因此,修改新对象会对原对象产
生影响


先从浅拷贝入手(基础版本)
简单思路:1.创建一个新对象
2.遍历要克隆的对象
3.给新对象添加上对应的成员
function qianClone(obj){
var newObj={};
for (var key in obj){
newObj[key]=obj[key]
}
return newObj;
}
var xm={
name:"xm",
age:30,
cars:{
bmw:"30w",
bench:"60w"
}
}
var newXm=qianClone(xm);
console.log(newXm)

newXm.name="Dm";
newXm.cars.bmw="40w";
console.log(newXm)
结果:

于是我们可以想到如何可以进行深层拷贝,将对象内部的对象也能完整的拷贝一份;
深拷贝
思考:如何简单修改浅拷贝的代码即可实现深拷贝? 修改浅拷贝的代码
function deepClone(obj) {
//如果不是复杂数据类型,就直接返回一个一样的对象
if(typeof obj !="object"){
return obj
}
//如果是,就递归调用
var newObj = {};
for (var key in obj) {
newObj[key] = deepClone(obj[key])
}
return newObj;
}
var newXm = deepClone(xm);
newXm.name = "Dm";
newXm.cars.bmw = "40w";
console.log(newXm);
console.log(xm)

显然需求已经实现,但是需不需要优化?
优化版本深拷贝
先看函数代码
function deepClone(obj) {
//如果不是复杂数据类型,就直接返回一个一样的对象
if(typeof obj !="object"){
return obj
}
//如果是,就递归调用
var newObj = {};
for (var key in obj) {
newObj[key] = deepClone(obj[key])
}
return newObj;
}
用几个常用数据测试一下上面函数
1.null
var o=deepClone(null)
console.log(o)
打印结果:

2.正则表达式
var RegExp=/[\u4e00-\u9fa5]/gm;
var o=deepClone(RegExp)
console.log(o)
打印结果:

3.日期对象
var RegExp=/[\u4e00-\u9fa5]/gm;
var o=deepClone(RegExp)
console.log(o)
打印结果:

4.数组对象
var arr=["牛爷爷","大头儿子","围裙妈妈"]
//不要管我为什么把他们仨放一组enmm
var o=deepClone(arr)
console.log(o)
打印结果:

显然结果均是错误的,因此,如何解决我们的deepClone的bug嘞?
解完bug代码:
function deepClone(obj) {
if (obj === null) return null; //null 的情况
if (obj instanceof RegExp) return new RegExp(obj); //正则表达式的情况
if (obj instanceof Date) return new Date(obj); //日期对象的情况
if (typeof obj == 'Function') return new function(obj){}; //函数的情况
if (typeof obj != "object") {
//非复杂类型,直接返回 也是结束递归的条件
return obj
}
//[].__proto__.constructor=Array()
//{}.__proto__.constructor=Object()
//因此处理数组的情况时,可以取巧用这个办法来new新对象
var newObj = new obj.__proto__.constructor;
for (var key in obj) {
newObj[key] = deepClone(obj[key])
}
return newObj;
}
//测试代码
var obj={
name:'xm',
birth:new Date,
desc:null,
reg:/^123$/,
ss:[1,2,3],
fn:function(){
console.log('123')
}
}
var obj2 = deepClone(obj);
console.log(obj,obj2)
obj.fn()
obj2.fn()
输出值:

补充说明:(以下也是面试常考)
1.typeof 和 instanceof的区别?
typeof可以判断出基本数据类型(当然除了null的数据类型为object的bug),还可以正确判断出某个对象是否为function,其余的Date,Array等无法判断
instanceof相反,可以准确判断出复杂数据类型,但是无法判断简单数据类型.
2.实例对象的原型链
看完不点赞的太过分了!!!!!!