浅拷贝踩坑
let obj={
name:"张三",
hobby:["游泳"]
}
let copy=obj
这是浅拷贝嘛?no 不是 这只是赋值
浅拷贝定义有两点:
1、需要生成一个新的对象(新地址)
2、对属性是引用数据类型的,直接赋值(拷贝地址值)
下面写一些浅拷贝方法
方法一
function shallowCopy(source){
let obj={};
for(let key in source){
obj[key]=source[key];
}
return obj
}
方法二
Object.assign(第一层的是“深拷贝”,深层的是“浅拷贝”)
Object.assign({},source)
方法三
扩展运算符 ... 实现的浅拷
let shallowCopy={...source}
方法四
let allDesc = Object.getOwnPropertyDescriptors(source);
let cloneObj = Object.create(Object.getPrototypeOf(source), allDesc);
深拷贝
let obj={
name:"张三",
hobby:["玩游戏"],
fn(){
console.log(this.name);
},
time:new Date(),
reg:new RegExp("\\w+")
};
方案一
console.log("@有问题的深拷贝",JSON.parse(JSON.stringify(obj)));
console.log("源对象",obj);
方案二
手写一个递归的深拷贝(初始版)
function deepClone(source){
if(source === null || typeof source !== "object" || source instanceof Date ||source instanceof RegExp || typeof source ==="number"){
return source;
}
let obj=Array.isArray(source)?[]:{};
for(let key in source){
if(Object.hasOwnProperty.call(source,key)){
obj[key]=deepClone(source[key]);
}
}
return obj;
}
上面初始版本会有一个问题????
遇到循环引用时,会失效。
let obj = {
name: "zs",
};
let obj1 = {
name: "obj1",
};
obj2 = {
name: "obj2",
};
obj.child = obj1;
obj1.child = obj2;
obj2.child = obj;
console.log(obj);
console.log(obj === obj.child.child.child);//true
let res= deepClone(obj)
console.log(res === res.child.child.child);//false
进阶版本
const map =new WeakMap();
function deepClone(source,targer={}){
if(source === null || typeof source !== "object" || source instanceof Date ||source instanceof RegExp || typeof source ==="number"){
return source;
}
if(map.get(source)){
return map.get(source);
}
let obj = Array.isArray(source)?[]:{};
let allDesc = Object.getOwnPropertyDescriptors(source);
let cloneObj = Object.create(Object.getPrototypeOf(source), allDesc);
//或者使用
//let cloneObj=Object.assign({},source);
map.set(source,cloneObj);
for(let key in cloneObj){
if(Object.hasOwnProperty.call(cloneObj,key)){
targer[key]=deepClone(source[key]);
cloneObj[key]=deepClone(cloneObj[key]);
}
}
return cloneObj;
}
实战应用
const map = new WeakMap();
let util = {
uuid: function (len, radix) {
var chars = uuidCharts,
uuid = [],
i;
radix = radix || chars.length;
len = len || 16;
if (len) {
// Compact form
for (i = 0; i < len; i++)
uuid[i] = chars[0 | (Math.random() * radix)];
} else {
// rfc4122, version 4 form
var r;
// rfc4122 requires these characters
uuid[8] = uuid[13] = uuid[18] = uuid[23] = "";
uuid[14] = "4";
// Fill in random data. At i==19 set the high bits of clock sequence as
// per rfc4122, sec. 4.1.5
for (i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | (Math.random() * 16);
uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
}
}
}
return uuid.join("");
},
deepClone: function (source, target = {}) {
if (
typeof source !== "object" ||
source instanceof Date ||
source instanceof RegExp ||
source === null ||
typeof source === "number"
) {
return source;
}
if (map.get(source)) {
return map.get(source);
}
let obj = Array.isArray(source) ? [] : {};
// let allDesc = Object.getOwnPropertyDescriptors(source);
// let cloneObj = Object.create(Object.getPrototypeOf(source), allDesc);
let cloneObj = Object.assign({},source);
map.set(source, cloneObj);
for (const key in cloneObj) {
if (Object.hasOwnProperty.call(cloneObj, key)) {
cloneObj[key] = dsf.deepClone(cloneObj[key], target);
target[key] = dsf.deepClone(source[key], target);
}
}
return cloneObj;
},
};
window.dsf = Object.create(util);
let copy = {
http: function () {},
base64: function () {},
md: function () {},
};
dsf.deepClone(copy, dsf);
console.log("dsf", dsf);