区别引用赋值、浅拷贝和深拷贝 给出一个举例对象:
const info = {
name:'jackson',
friend:{
name:'james'
}
}
引用赋值:
在内存中的引用相同
const obj1 = info
obj1.name = 'alvin'
console.log(info.name) //'alvin'
浅拷贝
用解构操作符:
const obj2 = {...info}
obj2.name = 'kobe'
console.log(info.name) // jackson //没有被改变
obj2.friend.name = 'kobe'
cosole.log(info.friend.name) // kobe //仍然被改变
用Object.assign:
const obj3 = Object.assign({},info)
obj3.name = 'kobe'
console.log(info.name) // jackson //没有被改变
obj3.friend.name = 'kobe'
console.log(info.friend.name) // kobe //仍然被改变
深拷贝 (JSON方法举例)
const obj4 = JSON.parse(JSON.stringify(info))
obj4.name = 'kobe'
console.log(info.name) // jackson //没有被改变
obj4.friend.name = 'kobe'
console.log(info.friend.name) // james //没有被改变
方法一:用JSON
const b = JSON.parse(JSON.stringify(a))
缺点:
- 不支持Date 正则 undefined 函数等数据
- 不支持引用(即环状结构)
- 然后引出方法二
方法二:递归
要点:
- 递归
- 判断类型
- 检查环
const deepClone = (a,cache) => {
if(!cache){
cache = new Map()
}
//不考虑 iframe
if (a instanceof Object) {
if (cache.get(a)) {
// 检查环
return cache.get(a)
}
let result = undefined
//Object
if (a instanceof Function) {
// 不能百分之百拷贝
if (a.prototype) {
//如果有prototype就是普通函数
result = function () {
return a.apply(this, arguments)
}
} else {
//箭头函数
result = (...args) => {
a.call(undefined, ...args)
}
}
} else if (a instanceof Array) {
// 数组
result = []
} else if (a instanceof Date) {
// 日期
result = new Date(a - 0)
} else if (a instanceof RegExp) {
// 正则
result = new RegExp(a.source, a.flags)
} else {
result = {}
}
cache.set(a, result)
for (let key in a) {
if (a.hasOwnProperty(key)) {
//如果属性是继承得到的,不应该拷贝,在该对象上,再拷贝
result[key] = deepClone(a[key],cache)
}
}
return result
} else {
//string number boolean null undefined symbol bigint
return a
}
}
//测试代码
const a = {
number: 1,
bool: false,
str: 'hi',
empty1: undefined,
empty2: null,
array: [
{ name: 'frank', age: 18 },
{ name: 'jacky', age: 19 },
],
date: new Date(2000, 0, 1, 20, 30, 0),
regex: /\.(j|t)sx/i,
obj: { name: 'frank', age: 18 },
f1: (a, b) => a + b,
f2: function (a, b) {
return a + b
},
}
a.self = a // 循环引用 没有出口
const b = deepClone(a)
b.self === b // true
b.self = 'hi'
a.self !== 'hi' //true
面试问到是什么深拷贝: 画图,表示两个对象直接没有交集,则是深拷贝。