/**
* 对象克隆
* 支持基本数据类型及对象
* 递归方法
*/
// 方法一:
function clone(obj) {
var o;
switch (typeof obj) {
case "undefined":
break;
case "string":
o = obj + "";
break;
case "number":
o = obj - 0;
break;
case "boolean":
o = obj;
break;
case "object": // object 分为两种情况 对象(Object)或数组(Array)
if (obj === null) {
o = null;
} else {
if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") {
o = [];
for (var i = 0; i < obj.length; i++) {
o.push(clone(obj[i]));
}
} else {
o = {};
for (var k in obj) {
o[k] = clone(obj[k]);
}
}
}
break;
default:
o = obj;
break;
}
return o;
}
//方法二:解决父子循环引用问题
// 深拷贝 解决父子循环引用问题
function deepCopy2(obj, parent=null) {
//创建一个新对象
let result = {};
let keys = Object.keys(obj),
key = null,
temp = null,
_parent = parent;
//该字段有父级则需要追溯该字段的父级
while(_parent) {
//如果该字段引用了它的父级,则为循环引用
if(_parent.originParent === obj) {
//循环引用返回同级的新对象
return _parent.currentParent;
}
_parent = _parent.parent
}
for(let i=0,len=keys.length;i<len;i++) {
key = keys[i]
temp = obj[key]
// 如果字段的值也是一个新对象
if(temp && typeof temp === 'object') {
result[key] = deepCopy2(temp, {
//递归执行深拷贝,将同级的待拷贝对象与新对象传递给parent,方便追溯循环引用
originParent: obj,
currentParent: result,
parent: parent
});
} else {
result[key] = temp;
}
}
return result;
}
const obj1 = {
x:1
}
obj1.z = obj1;
const obj2 = deepCopy2(obj1);
// 方法三:
// 深拷贝 解决兄弟循环引用问题
function deepCopy3(obj) {
// hash表,记录所有的对象的引用关系
let map = new WeakMap();
function dp(obj) {
let result = null;
let keys = Object.keys(obj);
let key = null,
temp = null,
existobj = null;
existobj = map.get(obj);
//如果这个对象已经被记录则直接返回
if(existobj) {
return existobj;
}
result = {}
map.set(obj, result);
for(let i =0,len=keys.length;i<len;i++) {
key = keys[i];
temp = obj[key];
if(temp && typeof temp === 'object') {
result[key] = dp(temp);
}else {
result[key] = temp;
}
}
return result;
}
return dp(obj);
}
const obj= {
a: {
name: 'a'
},
b: {
name: 'b'
},
c: {
}
};
c.d.e = obj.a;
const copy = deepCopy3(obj);
实现一个函数clone,可以对js中得基本数据类型进行值复制
最新推荐文章于 2022-09-03 00:32:58 发布