深拷贝的常用的几种方式
- Object.assign 其实是浅拷贝,但是数据如果只有一级,可以当作深拷贝使用;层级多的话 不可以
- JSON.parse(JSON.stringfy()) 有缺陷;如果有function会丢失;如果有Date数据类型,会转为字符串;undefined 会丢失;学习参考
function / symbol/ undefined :
let fn = function fn() {}
let un = undefined
let sym = Symbol('')
如果出现在数组中会转为null;
let arr = [fn, un, sym]
console.log(JSON.stringify(arr))
vconsole.min.js?65ce:10 [null,null,null]`
如果出现非数组对象中会被忽略; 非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中;
let obj = {fn: fn, un: un, sym: sym}
console.log(JSON.stringify(obj))
vconsole.min.js?65ce:10 {}
如果单独出现 则返回undefined;
console.log(JSON.stringify(fn))
vconsole.min.js?65ce:10 undefined
console.log(JSON.stringify(un))
vconsole.min.js?65ce:10 undefined
console.log(JSON.stringify(sym))
vconsole.min.js?65ce:10 undefined
JSON.stringfy 一共有三个参数, 第二个参数可以传入函数或者数组
传入函数的话: 作为函数,它有两个参数,键(key)和值(value),它们都会被序列化。
传入数组:数组的值代表将被序列化成 JSON 字符串的属性名
- 自己手写deepCopy
function deepCopy(data) {
if(!data) return
if(Object.prototype.toString.call(data) == '[object Array]')
{
let newData = []
for (const key in data) {
newData[key] = deepCopy(data[key])
}
return newData
} else if(Object.prototype.toString.call(data) == '[object Object]')
{
let newData = {}
for (const key in data) {
newData[key] = deepCopy(data[key])
}
return newData
} else if(Object.prototype.toString.call(data) == '[object Funtion]')
{
return new Function(`return ${data.toString()}`).call(this)
}else if(Object.prototype.toString.call(data) == '[object Date]')
{
return new Date(data.valueOf())
}else if(Object.prototype.toString.call(data) == '[object RegExp')
{
return new RegExp(data)
}else if(Object.prototype.toString.call(data) == '[object Set]')
{
let set = new Set()
for (const v of data) {
set.add(clone(v))
}
return set
}else if(Object.prototype.toString.call(data) == '[object Map]')
{
let map = new Map()
data.forEach((k, v) => {
map.set(k, deepCopy(v))
})
return map
}
return data
}
- 使用lodash 库
如果对你有帮助,麻烦点个赞 谢谢~~