深拷贝

浅拷贝

学深拷贝之前我们先了解一下浅拷贝
image.png
上面可以看到两个对象变成了一样的,由此可以得出浅拷贝只能拷贝一层。

深拷贝

1 JSON.parse(JSON.stringify())

这种深拷贝方式会有几个问题,让我们来看一下。

  • 1 时间和正则的问题

使用这个方法执行后时间格式会变成字符串格式(正则同理)
image.png

  • 2 丢失和类型

使用序列化之后会导致函数丢失,obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
image.png

自己实现一个深拷贝

/*
* 数据类型:基本数据类型,引用数据类型;
* 基本数据类型:String,null,undefined,Number,Boolean
* 引用数据类型:RegExp,Date,Array,object,Function
* */
function deepClone(value) {
    //判断是否为null/undefined,因为在不是===的情况下 null=undefined if (value == undefined) return;
    //判断是否是正则
 if (value instanceof RegExp) return new RegExp(value);
    //判断是否是时间格式
 if (value instanceof Date) return new Date(value);
    //判断是否是String,Number,Boolean,Function(因为函数不会进行拷贝,直接执行)
 if (typeof value != 'object') return value;
    // 能走到这里的只有数组和对象了
 //value.constructor指向构造函数本身 Array/Object. new Array/new Object生成的就是[]/{}
 let container = new value.constructor;
    for (let key in value) {
        container[key] = deepClone(value[key])
    }
    return container
}
let obj = {
    a: [1, 2],
    b: 500
};
let objCopy = deepClone(obj);
obj.a[0]=100;
console.log('我是obj', obj);
console.log('我是objCopy', objCopy);

上面基本实现了一个深拷贝,但是在这个方法中还存在些问题。如果我传入这样一个对象那么就会出现爆栈的现象。

let b={};
let a = {b:b};
b.a=a;
let copy = deepClone(a);
console.log(copy);

浏览器报错:
image.png

这个方法显然不是很友好,那么我们使用Map和Set函数来优化一下,如果在Map中能找到直接使用Map中的即可;
完整代码:

/*
* 数据类型:基本数据类型,引用数据类型;
* 基本数据类型:String,null,undefined,Number,Boolean
* 引用数据类型:RegExp,Date,Array,object,Function
* */
//传入map
function deepClone(value, hash = new Map()) {
    //判断是否为null/undefined,因为在不是===的情况下 null=undefined if (value == undefined) return;
    //判断是否是正则
 if (value instanceof RegExp) return new RegExp(value);
    //判断是否是时间格式
 if (value instanceof Date) return new Date(value);
    //判断是否是String,Number,Boolean,Function(因为函数不会进行拷贝,直接执行)
 if (typeof value != 'object') return value;
    //进来先判断是不是在map中,如果存在直接获取,就不需要再执行下面的deepClone函数进行递归为浏览器开辟无数个新的内存了。
 if (hash.get(value)) {
        return value;
    }
    // 能走到这里的只有数组和对象了
 //value.constructor指向构造函数本身 Array/Object. new Array/new Object生成的就是[]/{}
 let container = new value.constructor;
    //每次进来向map函数中存值
 hash.set(value, container)
    for (let key in value) {
        container[key] = deepClone(value[key], hash)
    }
    return container
}
let b = {};
let a = {b: b};
b.a = a;
let copy = deepClone(a);
console.log(copy);

输出结果
image.png

你可能感兴趣的:(深拷贝,javascript)