学习消除循环引用

  1. 创建循环引用对象

    // 创建一个循环引用的对象
    let a = {};
    let b = {};
    a.b = b;
    b.a = a;
    
  2. 打印上述对象a或b,会得到一个无限嵌套互相引用的对象

  3. 结束(解除)多余的引用嵌套(具体思路请看超详细注释)

    		/**
         * 解除循环引用
         * @param object    循环引用对象
         * @param replacer  重构对象的回调函数
         * @returns {{_$}}  解除循环引用的占位对象
         */
        const fixReference = (object, replacer) => {
            // 使用闭包和WeakMap对象的set、get嗅探重复的对象
            const objects = new WeakMap();
            // 传入需解除引用的对象和默认的终止引用占位
            const terminate = (value, path) => {
    
                // 识别并终止引用和重构重复对象
                let old_path;
                // 新子对象
                let _obj;
    
                // 回调函数,修改传入对象
                if (replacer !== undefined) {
                    value = replacer(value);
                }
    
                // 排除基本类型、null、reg对象、date对象,反之直接return自身
                if (
                    typeof value === 'object'
                    && value !== null
                    && !(value instanceof Boolean)
                    && !(value instanceof Date)
                    && !(value instanceof Number)
                    && !(value instanceof RegExp)
                    && !(value instanceof String)
                ) {
    
                    // 尝试根据当前对象获取key对应的value
                    old_path = objects.get(value);
                    if (old_path !== undefined) {
                        // 如果重复则返回重构的对象(old_path为重复对象WeakMap中存储的value)
                        return {_$: old_path};
                    }
    
                    // 无重复则用当前对象设置key和对应的value
                    objects.set(value, path);
    
                    // 根据数组或对象不断递归每一个key,消除引用返回key对应的value或者_obj
                    if (Array.isArray(value)) {
                        _obj = [];
                        // 键值和默认path拼接新的path
                        value.forEach((item, index) => _obj[index] = terminate(item, `${path}[${index}]`));
                    } else {
                        _obj = {};
                        Object.keys(value).forEach(key =>  _obj[key] = terminate(
                            value[key],
                            // 键值和默认path拼接新的path
                            `${path}[${JSON.stringify(key)}]`
                        ));
                    }
                    // return 重组后的子对象
                    return _obj;
                }
                // return 自身
                return value;
            };
    
            return terminate(object, 'stop')
        }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值