1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| const isComplexDataType = (obj) => (typeof obj === "object" || typeof obj === "function") && obj !== null;
const deepClone = function (obj, hash = new WeakMap()) { if (obj.constructor === Date) return new Date(obj); // 日期对象直接返回一个新的日期对象
if (obj.constructor === RegExp) return new RegExp(obj); //正则对象直接返回一个新的正则对象
//如果循环引用了就用 weakMap 来解决
if (hash.has(obj)) return hash.get(obj);
let allDesc = Object.getOwnPropertyDescriptors(obj);
//遍历传入参数所有键的特性
let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc);
//继承原型链
hash.set(obj, cloneObj);
for (let key of Reflect.ownKeys(obj)) { cloneObj[key] = isComplexDataType(obj[key]) && typeof obj[key] !== "function" ? deepClone(obj[key], hash) : obj[key]; }
return cloneObj; };
// 下面是验证代码
let obj = { num: 0,
str: "",
boolean: true,
unf: undefined,
nul: null,
obj: { name: "我是一个对象", id: 1 },
arr: [0, 1, 2],
func: function () { console.log("我是一个函数"); },
date: new Date(0),
reg: new RegExp("/我是一个正则/ig"),
[Symbol("1")]: 1, };
Object.defineProperty(obj, "innumerable", { enumerable: false, value: "不可枚举属性", });
obj = Object.create(obj, Object.getOwnPropertyDescriptors(obj));
obj.loop = obj; // 设置loop成循环引用的属性
let cloneObj = deepClone(obj);
cloneObj.arr.push(4);
console.log("obj", obj);
console.log("cloneObj", cloneObj);
|