深拷贝函数的实现

使用JSON.parse(Json.stringify())实现深拷贝有哪些坑?

  • 如果属性值是undefined、或者函数,序列化后属性丢失;
  • 如果属性值是RegExp、Error对象,序列化后值是{};
  • 如果属性值是NaN、Infinity和-Infinity,则序列化的结果会变成null

因此一般都采用自定义函数实现:

复制代码
function deepClone(obj, map = new WeakMap()) {
    // 不是对象,直接返回(包括基础数据类型、 `null` 和 `undefined`)
    if (obj === null || obj === undefined || typeof obj !== "object") return obj;
    // 避免循环引用
    if (map.has(obj)) return map.get(obj);
    // 处理特殊对象(Date / RegExp)
    if (obj instanceof Date) return new Date(obj);
    if (obj instanceof RegExp) return new RegExp(obj);
    //创建新对象或数组
    const cloneObj = Array.isArray(obj) ? [] : {};
    // 存入 `WeakMap`,防止循环引用
    map.set(obj, cloneObj);
    //获取所有键,包括 `Symbol`
    const keys = Reflect.ownKeys(obj); 
    //递归拷贝属性
    keys.forEach((key) => {
        cloneObj[key] = deepClone(obj[key], map);
    });
    return cloneObj;
}

//测试用例
const obj1 = {
    num: 1,
    str: "hello",
    arr: [1, 2, { a: 3 }],
    obj: { x: 10 },
    date: new Date(),
    regex: /abc/g,
    sym: Symbol("sym"),
};
obj1.self = obj1; // 🌀 创建循环引用

const clone = deepClone(obj1);
console.log(clone);
console.log(clone === obj1); // false 证明是深拷贝
console.log(clone.arr === obj1.arr); // false 证明数组被深拷贝
console.log(clone.obj === obj1.obj); // false 证明对象被深拷贝
console.log(clone.date === obj1.date); // false 证明 Date 被拷贝
console.log(clone.regex === obj1.regex); // false 证明 RegExp 被拷贝
console.log(clone.self === clone); // true 证明循环引用正确处理
复制代码

 

posted @   我是格鲁特  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示