JS实现深拷贝(解决循环引用等问题)

基本思路是递归,主要是需要针对不同的数据类型(null, 数组,Date,正则表达式 等)进行精细的处理,并且用WeakMap解决循环引用,避免陷入死循环。

函数的深拷贝暂时没有思路,用 new Function(fn.toString()) 会有些问题,所以直接拷贝引用了,请大家赐教。

 

复制代码
/**
 * 深拷贝
 */

const wm = new WeakMap();

function deepClone(target) {
    let result;
    if (typeof target === 'object') {
        // null
        if (target === null) {
            result = target;
        }
        // Array
        else if (Array.isArray(target)) {
            result = [];
            target.forEach(item => result.push(deepClone(item)));
        }
        // Date
        else if (target instanceof Date) {
            result = new Date(target);
        }
        // regular expression
        else if (target instanceof RegExp) {
            result = new RegExp(target);
        }
        // plain object
        else {
            // detect circular reference
            // 用WeakMap的key保存原对象的引用记录, value是对应的深拷贝对象的引用
            // 例如: a:{b:{c:{d: null}}}, d=a, a 的深拷贝对象是 copy, 则 weakmap 里保存一条 a->copy 记录
            //     当递归拷贝到d, 发现d指向a,而a已经存在于weakmap,则让新d指向copy
            if (wm.has(target)) {
                result = wm.get(target);
            }
            else {
                result = {};
                wm.set(target, result);
                for (let prop in target) {
                    result[prop] = deepClone(target[prop]);
                }
            }
        }
    }
    // function, primary type
    else {
        result = target;
    }
    return result;
}

(function () {
    const a = {
        num: 123,
        say() {
            return 'Hello';
        },
        arr: [1, 2, [4, {name: 'Jack'}]],
        n: null,
        un: undefined,
        d: new Date(),
        reg: /[a-z0-9]+/,
        b: {
            c: {
                d: null
            }
        }
    };
    a.b.c.d = a;
    const copy = deepClone(a);
    console.log(copy)
    console.log(copy === a) // false
    console.log(copy.say()); // Hello
    console.log(copy.arr);
    console.log(copy.arr[2][1] === a.arr[2][1]); // false
    console.log(copy.b.c.d === copy) // true,循环引用得到复制
})();
复制代码

posted on   大唐西域都护  阅读(2073)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2017-05-12 漫话JavaScript与异步·第二话——Promise:一诺千金

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示