1、最简单最省事JSON
问题:function 和 undefined 两种类型的值会被忽略(不考虑自定义和API中提供的复杂类型)
function clone(obj) {
return JSON.parse(JSON.stringify(obj))
}
2、使用JQuery
问题:循环引用会导致内存溢出
$.extend( [deep ], target, object1 [, objectN ] )
3、自己实现
版本1.0,简单实现,递归运行效率低,次数过多的话容易造成栈溢出。
function clone(obj) {
if(typeof obj === 'object') {
let result
if(Array.isArray(obj)) {
result = []
for(let i = 0; i < obj.length; i++) {
result[i] = clone(obj[i])
}
} else {
result = {}
for(let key in obj) {
result[key] = clone(obj[key])
}
}
return result
} else {
return obj
}
}
版本2.0 解决循环引用和平级引用的问题
function clone(target) {
let map = new Map()
const dfs = obj => {
if(map.has(obj)) return map.get(obj)
if(typeof obj === 'object') {
let result
if(Array.isArray(obj)) {
result = []
map.set(obj, result)
for(let i = 0; i < obj.length; i++) {
result[i] = dfs(obj[i])
}
} else {
result = {}
map.set(obj, result)
for(let key in obj) {
result[key] = dfs(obj[key])
}
}
return result
} else {
return obj
}
}
return dfs(target)
}
版本3.0,考虑正则和Date类型数据
function clone(target) {
let map = new Map()
const dfs = obj => {
if(map.has(obj)) return map.get(obj)
if(typeof obj === 'object') {
let result
if(Array.isArray(obj)) {
result = []
map.set(obj, result)
for(let i = 0; i < obj.length; i++) {
result[i] = dfs(obj[i])
}
} else if(obj instanceof RegExp) {
result = new RegExp(obj)
} else if(obj instanceof Date) {
result = new Date(obj)
} else {
result = {}
map.set(obj, result)
for(let key in obj) {
result[key] = dfs(obj[key])
}
}
return result
} else {
return obj
}
}
return dfs(target)
}