使用Object.assign()拷贝对象存在的问题
Object.assign()实现的是浅拷贝
// 对基本数据类型没有问题,但是对引用数据类型的时候有些属性就会丢掉,如属性g
let target = {
a: {
b: {
c: 1
},
e: 4,
f: 5,
g: 6
}
}
let source = {
a: {
b: {
c: 1
},
e: 2,
f: 3
}
}
console.log(Object.assign(target,source));
基本数据类型中简单的深拷贝
当a发生变化的时候b并没有随着a发生变化,这叫深拷贝,2个值不相互影响
let a = 5
let b = a
a = 6
console.log(a,b); // 6 5
对象的浅拷贝
// 浅拷贝:obj1和obj2在内存中存的是相同的内存地址
let obj1 = {
name: 'lee',
age: '32'
}
let obj2 = obj1
obj1.age = 18
console.log(obj1); // {name: 'lee', age: 18}
console.log(obj2); // {name: 'lee', age: 18}
如何改为深拷贝
1.使用JSON.parse()和JSON.stringfy()
让obj1 和 obj2 不相互干扰,实现深拷贝
使用JSON.parse()和JSON.stringfy()实现深拷贝(不支持对函数进行深拷贝)
-
JSON.parse(): 将JSON字符串转成对象
-
JSON.stringfy():将对象转成字符串
思路:先用 JSON.stringfy()将对象转成字符串,再使用SON.parse()转成对象
// obj1中的age值发生变化,但是obj2并不受影响
let obj1 = {
name: 'lee',
age: '32'
}
let str = JSON.stringify(obj1)
let obj2 = JSON.parse(str)
obj1.age = 18
console.log(obj2); // {name: 'lee', age: '32'}
上面obj1和obj2是2个独立的对象,再堆内存中存的是2个不同的内存地址,因此它们彼此不相互干扰
2.使用递归自己实现一个深拷贝的函数(适用于基本数据类型、数组和对象)
如何判断数据类型 - 通过toString()方法判断数据类型
typeOf()只能判断基本数据类型,不能判断引用数据类型
let checkType = data =>{
console.log(Object.prototype.toString.call(data));
}
checkType([]) // "[object Array]"
通过对象原型上的tosString方法得到数据类型的字符串形式,下面还需对这个字符串进行截取,只想要Array
let checkType = data =>{
console.log(Object.prototype.toString.call(data).slice(8,-1));
}
checkType([]) // Array
使用递归实现深拷贝
let checkType = data => {
return Object.prototype.toString.call(data).slice(8, -1);
}
let deepClone = source => {
let sourceType = checkType(source)
let result
if(sourceType === 'Object'){
result = {}
}else if(sourceType === 'Array'){
result = []
}else{
return source
}
for(let i in source){
let value = source[i]
let valueType = checkType(value)
if(valueType === 'Object' || valueType === 'Array'){
// 递归
result[i] = deepClone(value)
}else{
result[i] = value
}
}
return result
}
// arr1值的改变不影响arr2
let arr1 = {name:'lee',age:18}
let arr2 = deepClone(arr1)
arr1.age = '32'
console.log(arr1); // {name:'lee',age:32}
console.log(arr2); // {name:'lee',age:18}
// obj1值的改变不影响obj2
let obj1 = {
name: 'lee',
like:['读书','打游戏']
}
let obj2 = deepClone(obj1)
obj1.like[0] = '跑步'
console.log(obj1); //
console.log(obj2);