实现deepClone的三种方式
文章的开头总是很难水的,从前的作文也没有到过800字
深拷贝 和 浅拷贝(仅对引用类型,简单类型没有深浅拷贝的说法)
深拷贝和浅拷贝的区别
深拷贝:值拷贝,原数据改变不会影响拷贝后的数据
浅拷贝:引用地址拷贝,与其说是数据相互影响,实际上是同一个数据,就像你和你弟弟的爸爸,你弟弟的爸爸捡到了100元,等同于你的爸爸也捡到了100元
赋值操作也是最常见的浅拷贝
const obj1 = { name:"小帅哥" }
const obj2 = obj1
obj1.name = '大帅哥'
console.log(obj2.name) // 大帅哥
如何实现深拷贝? 这里提供3种方式,很多人不知道这第3种
利用 JSON.stringify() 和 JSON.parse()
JSON.stringify()
方法将一个 JavaScript 对象或值转换为 JSON 字符串
JSON.parse()
方法用来解析 JSON 字符串,构造由字符串描述的 JavaScript 值或对象
优点:最简单, JavaScript 原生方法
缺点:
- 当值为 function , undefined ,symble 时会丢失
- 当值为 NaN , + - infinity 时,会被序列化为 null
- 循环引用直接报错
const obj = {
a:Symbol(1),
b:1,
c:NaN,
d:()=>{},
e:Infinity
}
console.log(JSON.parse(JSON.stringify(obj))); // { b: 1, c: null, e: null }
当然是自己写一个简单的了
应该算是简单,我觉得 function 没有必要拷贝,如果在对象里面,直接返回就行了,Date Error RegExp
function deepClone(object) {
// 如果是简单类型 或者 null 或者 function 直接返回
if (typeof object !== 'object' || object == null) {
return object
}
// 类型映射对象
const hashMap = {
'[object Object]': {},
'[object Array]': []
}
// 处理循环引用
const map = new Map()
// 递归调用的函数
function deepCloneTool(object) {
// 如果是简单类型 或者 null 或者 function 直接返回
if (typeof object !== 'object' || object == null) {
return object
}
用来处理循环引用
if (map.has(object)) {
return map.get(object)
}
// 获取数据类型
const type = Object.prototype.toString.call(object)
// 返回结果
const result = hashMap[type] || null
map.set(object,result)
// 这里可能存在 Date Error RegExp Map WeakMap Set WeakSet (有兴趣可以自己补一下)
if (!result) {
return '出现意料之外的类型'
}
for (let key in object) {
const val = object[key]
result[key] = deepCloneTool(val)
}
return result
}
return deepCloneTool(object)
}
通过 MessageChannel
MessageChannel
接口允许我们创建一个新的消息通道,并通过它的两个 MessagePort
属性发送数据。
信息在通道中传输的时候,也会有一个序列化的和反序列化的过程
缺点:当属性中含有 function symble 会报错
function deepClone(obj) {
return new Promise((resolve, reject) => {
const { port1, port2 } = new MessageChannel()
port1.postMessage(obj)
port2.onmessage = msg => {
resolve(msg.data)
}
})
}
deepClone({ name: '大帅哥' }).then(res => {
console.log(res); // { name:'大帅哥' }
})
转载自:https://juejin.cn/post/7205192064212992060