• 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,循环引用得到复制
    })();
  • 相关阅读:
    css3 动画+动画库
    垃圾回收 及 内存泄漏
    做菜体会
    微信小程序
    微信公众号2
    JavaScript 原生事件
    Bootstrap框架
    Less 和 Sass
    HTML标签总结
    表单元素
  • 原文地址:https://www.cnblogs.com/leegent/p/14759524.html
Copyright © 2020-2023  润新知