一般实现方式有两种:
-
JSON.parse(JSON.stringify(obj))
,用法说明参考developer.mozilla.org/zh-CN/docs/…注意点,不可枚举、undefined、函数、symbol是不能
stringify
的,另外循环引用会报错,如下:
json.stringify
的第二个参数)
var cache = []
JSON.stringify(json, (key, value) => {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
return // 或者 return undefined
}
cache.push(value)
}
return value;
})
复制代码
-
直接实现:
从上面的stringify的用法,就会发现弊端,如无法拷贝函数引用等等以及循环引用的bug,不过处理循环无污染的方式是用一个数组记录(污染的方式是对每一个对象添加一个
__used
的属性标记改对象已被使用,无需再调用赋值),具体代码如下:
function deepClone(obj) {
const rootObj = {} // 记录新的对象
const cache = [obj] // 引用对象数组
const cacheNewValues = [rootObj] // 记录对应引用的新值
const assign = (innerObj) => {
const newObj = innerObj === obj ? rootObj : {}
Object.keys(innerObj).forEach(key => {
const value = innerObj[key]
const index = cache.indexOf(value)
// 未缓存
if(index === -1) {
const type = Object.prototype.toString.call(value)
if (typeof type === 'object') {
newObj[key] = assign(value)
// 记录引用的对象以及对应引用的新值
cache.push(value)
cacheNewValues.push(newObj[key])
} else {
newObj[key] = value
}
} else {
// 已缓存,取对应缓存的新值
newObj[key] = cacheNewValues[index]
}
})
return newObj
}
return assign(obj);
};
复制代码
运行如下:
思考: 栈溢出了呢? 下次更新这个问题