Skip to content

栈实现深拷贝

JavaScript 中,利用栈(或者称为迭代)来实现深拷贝可以避免使用递归,防止堆栈溢出,同时也能实现相同的效果。下面是一个利用栈实现深拷贝的代码:

js
function deepClone(obj) {
    // 使用一个栈来辅助进行迭代
    let stack = [];
    let cloned; // 存储拷贝后的对象或数组

    // 判断传入的数据类型
    if (Array.isArray(obj)) {
        cloned = []; // 如果是数组,则创建一个新的数组作为拷贝对象
    } else if (typeof obj === 'object' && obj !== null) {
        cloned = {}; // 如果是对象,则创建一个新的对象作为拷贝对象
    } else {
        return obj; // 如果是基本数据类型,则直接返回
    }

    // 初始状态:将原始对象和对应的拷贝对象入栈
    stack.push({
        original: obj,
        copy: cloned
    });

    // 迭代过程
    while (stack.length > 0) {
        let current = stack.pop(); // 弹出栈顶元素
        let original = current.original;
        let copy = current.copy;

        // 遍历原始对象的每一个属性
        for (let key in original) {
            if (original.hasOwnProperty(key)) {
                let value = original[key];

                // 如果属性值是对象或数组,则需要拷贝这个对象或数组
                if (typeof value === 'object' && value !== null) {
                    // 创建一个新的对象或数组作为拷贝对象的属性值
                    copy[key] = Array.isArray(value) ? [] : {};

                    // 将原始对象和对应的拷贝对象入栈,继续处理内部对象或数组
                    stack.push({
                        original: value,
                        copy: copy[key]
                    });
                } else {
                    // 如果属性值不是对象或数组,则直接赋值给拷贝对象的属性
                    copy[key] = value;
                }
            }
        }
    }

    return cloned;
}

// 测试深拷贝函数
let obj = [{
    a: 1,
    b: {
        c: 2,
        d: [3, 4],
        e: {
            f: 5,
            g: 6,
            h: [7, 8],
            i: function () {
                let a = 222
                console.log(a)
            }
        }
    }
}];
let clonedObj = deepClone(obj);
console.log(clonedObj);

// 验证结果
clonedObj[0].a = 100
clonedObj[0].b.e.h[1] = 800
clonedObj[0].b.e.i = function () {
    let a = 333
    console.log(a)
};
console.log(clonedObj, obj);
clonedObj[0].b.e.i(); // 333
obj[0].b.e.i(); // 222

在这个示例中,deepClone 函数使用一个栈 stack 来辅助进行迭代。初始时,将要拷贝的原始对象 obj 和对应的拷贝对象 cloned 入栈。然后,通过不断迭代栈中的元素,遍历原始对象的每一个属性,如果属性值是对象,则继续将其入栈以进行深层拷贝,直到完成整个对象的拷贝。最终,返回拷贝后的对象 clonedObj

这种方法可以有效地实现深拷贝,避免了递归可能导致的堆栈溢出问题,并且能够处理任意深度的嵌套对象或数组。

深拷贝函数在判断传入数据类型时,如果是数组则创建一个新数组作为拷贝对象,如果是对象则创建一个新对象作为拷贝对象,其他基本数据类型则直接返回,保持深拷贝后返回的数据类型与传入时相同。

基于 MIT 许可发布