深拷贝 BFS 问题

// 更精确的判断object函数
function isObject(obj) {
    return Object.prototype.toString.call(obj) == '[object Object]'
}

function cloneBFS(obj) {
    var target = {}; // target是我们最终得到的对象
    var arr = [obj]; // 用来保存对象,以便遍历
    const map = new Map(); 
    map.set(obj, target);  // 建立对象节点与克隆节点的映射关系
    while (arr.length > 0) {
        const curObj = arr.shift();
        // 遍历对象
        Object.keys(curObj).map(key => {
            const value = curObj[key];
            // 如果是对象,则放入arr数组里面,以下次继续遍历
            if (isObject(value)) {
                // 如果对象已经存在表中,说明存在循环引用
                if (map.has(value)) {
                   map.set(curObj, value);  // 这里看不懂
                } else {
                    // 建立这个属性对象与克隆节点的映射关系
                    map.set(value, {})
                    arr.push(value);
                }
            }
            // 赋值
            const clone = map.get(curObj);  // 拿到这个对象
            clone[key] = value;
        })
    }
    return target;
}

var obj = {
    name: "muyiy",
    book: {
        title: "You Don't Know JS",
        price: "45",
        b: {
            name: '小b',
            age: 16,
            next: {
                name: '小二'
            }
        }
    },
    a1: undefined,
    a2: null,
    a3: 123
}
obj.a4 = obj
console.log(cloneBFS(obj))

如上深拷贝算法,
`map.set(curObj, value); // 这里看不懂

有大佬知道吗

阅读 2.2k
1 个回答

这里主要解决循环引用的问题:
即:

var obj = {
    name: "muyiy",
    book: {
        title: "You Don't Know JS",
        price: "45",
        b: {
            name: '小b',
            age: 16,
            next: {
                name: '小二'
            }
        }
    },
    a1: undefined,
    a2: null,
    a3: 123
}
obj.a4 = obj // 循环引用

怎么解决的呢:Map可以用对象作为键来存储对应的数据,拷贝到这里时obj就是键,但由于在执行
cloneBFS(obj)第一步时,obj就作为键存储过了,所以在遍历到obj.a4(指向obj)时,这个
map.has(value)是为真,就不需要建立新的键值对和深拷贝,不然就会堆栈溢出;然后
const clone = map.get(curObj),通过map去将已存在的对象指针赋给obj.a4

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题