基于TDD,实现深拷贝
测试采用 Jest ,需要注意的是,使用import导入,需要配置babel
首先,我们来写一份测试用例
import { clone } from "./deepClone.js"
describe("test deep clone", () => {
it("case 1", () => {
const target = {
a: 1, // 数字
b: "string", // 字符串
d: {
// 子节点
child: "child"
}
}
const result = clone(target)
expect(result).toStrictEqual(target)
})
it("case 2 null", () => {
const target = {
a: 1,
b: "string",
c: undefined, // null
d: {
child: "child"
}
}
const result = clone(target)
expect(result).toStrictEqual(target)
})
it("case 3 Array", () => {
const target = {
a: 1,
b: "string",
c: undefined,
d: {
child: "child"
},
e: [1, 2, 3]
}
const result = clone(target)
expect(result).toStrictEqual(target)
})
it("case 4 Circular reference", () => {
const target = {
a: 1,
b: "string",
c: undefined,
d: {
child: "child"
},
e: [1, 2, 3]
}
target.target = target
const result = clone(target)
expect(result).toStrictEqual(target)
})
})
case 1
这里,我们常见的拷贝可以使用JSON.parse(JSON.stringify(target))
// deepClone.js
export function clone(target) {
return JSON.parse(JSON.stringify(target))
}
case 2 空值处理
上述的代码,遇到undefined的时候,会移除掉这个元素,所以上述方法并不适用,我们可以尝试写出以下代码
// deepClone.js
export function clone(target) {
// 当target是对象时处理
if (typeof target === 'object') {
let newTarget = {}
for (const key in target) {
newTarget[key] = clone(target[key])
}
return newTarget
} else {
return target
}
}
case 3 数组
测试用例加入了数组
这时候需要对Array这种特殊的object做处理
// deepClone.js
export function clone(target) {
if (typeof target === 'object') {
// 对数组进行处理
let newTarget = Array.isArray(target) ? [] : {}
for (const key in target) {
newTarget[key] = clone(target[key])
}
return newTarget
} else {
return target
}
}
case 4 循环引用
// deepClone.js
export function clone(target, map = new Map()) {
if (typeof target === 'object') {
let newTarget = Array.isArray(target) ? [] : {}
if (map.get(target)) {
return map.get(target)
}
map.set(target, newTarget)
for (const key in target) {
newTarget[key] = clone(target[key], map)
}
return newTarget
} else {
return target
}
}
测试愉快地通过了