js ES5和ES6 版本的对象深拷贝(JavaScript对象深拷贝)
偶尔我们会使用一下js对象的深拷贝
直接上代码
- 先准备一个需要拷贝的 对象
var obj = {
name:'小小叔',
age:34,
info: {
hobby: ['travel', 'piano', {a:1}],
career: {
teacher:4,
engineer:9
}
},
fun(){
console.log('一个方法');
}
}
2. ES5 规范 版本
function deepCloneEs5 (origin, target) {
var tar = target || {};
var toStr = Object.prototype.toString;
var arrType = '[object Array]';
for(var k in origin){
if (origin.hasOwnProperty(k)){
if (typeof origin[k] === 'object' && origin[k] !== null) {
tar[k] = toStr.call(origin[k]) === arrType ? [] : {};
deepCloneEs5(origin[k],tar[k])
} else {
tar[k] = origin[k];
}
}
}
return tar;
}
3. ES6 版本
// null undefined Date RegExp instanceof
// function 就先不理他,或者弄成字符串形式存着
function deepCloneEs6 (origin,hashMap = new WeakMap()) {
// 判断是不是 null和undefind (双== 可以两个同时判断,三===,是不行的) , 是不是对象
if (origin == undefined || typeof origin !== 'object') {
return origin;
}
// 如果是一个日期类型的 返回一个日期
if (origin instanceof Date) {
return new Date(origin);
}
// 如果是正则类型的 返回正则
if (origin instanceof RegExp) {
return new RegExp(origin);
}
// 判断 健名是不是已经存在,也就是拷贝过了的健名,拷贝过了直接使用,就不再继续深拷贝
const hashKey = hashMap.get(origin);
if (hashKey) {
return hashKey;
}
// 使用origin 的构造器来创建 target ,这样就不用去判断他是 [] 还是 {},
// 例如 const arr = []; const arr2 = new arr.constructor(); arr是数组,arr2也会是数组
// 例如 const obj = obj; const obj2 = new obj.constructor(); obj是对象,obj2也会是对象
const target = new origin.constructor();
// 这里把健名存入 hashMap
hashMap.set(origin,target);
for (let k in origin) {
if (origin.hasOwnProperty(k)) {
target[k] = deepCloneEs6(origin[k],hashMap);
}
}
return target;
}
4.例子实践
这个使用 ES6 规范的版本,主要是这个对象嵌套引用,得用 WeakMap 来优化一下
let test1 = {};
let test2 = {};
test2.test1 = test1;
test1.test2 = test2;
console.log(deepCloneEs6(test2));