栈实现深拷贝
在 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
。
这种方法可以有效地实现深拷贝,避免了递归可能导致的堆栈溢出问题,并且能够处理任意深度的嵌套对象或数组。
深拷贝函数在判断传入数据类型时,如果是数组则创建一个新数组作为拷贝对象,如果是对象则创建一个新对象作为拷贝对象,其他基本数据类型则直接返回,保持深拷贝后返回的数据类型与传入时相同。