我们在面试中会经常碰到深浅拷贝的问题,那么它是如何实现的呢?
1.Javascript的数据类型
- 基本类型:undefined、null、Boolean、String、Number、Symbol、Bigint
- 引用类型:Object、Array、Date、Function、RegExp 不同类型的储存方式
- 基本类型:基本类型值是有固定大小的储存在栈内存中
- 引用类型:引用类型的值是对象,保存在堆内存中,栈里面只保存了对象的变量标识符和对象在堆内存中的存储地址
2.深拷贝
深拷贝复制的是对象的实例,在栈内存中会重新分配内存,不同的地址,相同的值,互不影响。可以简单理解为用自己的基因复制了一个克隆人,虽然俩个是一模一样的,但这俩个之间并不会互相影响。 我们看一个例子:
let a = 1
let b = a
a = 2
输出: a=2 b=1
俩个为基本类型,储存在栈空间中,栈空间为b开辟了一个新的内存空间,值为a。此时对a进行修改,b并不会收到影响。
3.浅拷贝
浅拷贝复制的是对象的引用,相当于将A变量的指针赋值给新变量B,此时的新变量B的指针也指向A变量所指向的对象。当其中一个变量修改对象的值后,另一个变量也会发生变化。 我们看一个例子:
let person = {name : '冰墩墩',age :18}
let person2 = person
person.age = 19
console.log(person2.age); //19
对象是引用类型,所以person2的指针和person的指针指向同一个对象,当对象被修改时,都会受到影响。
``
- JSON.parse()和JSON.stringify() 可以用来深拷贝一个对象
- JSON.stringify():把一个js对象序列化为一个JSON字符串
- JSON.parse():把JSON字符串反序列化为一个js对象
看下面一个例子:
let arr = [1,2,3,4,5]
let arr2 =JSON.parse(JSON.stringify(arr))
arr[0] = 0
console.log(arr2); // [1,2,3,4,5]
4.手写实现深拷贝函数
要求:实现一个深拷贝对象的函数
let person = {
name: '冰墩墩',
age: 18,
like: {
sport: 'running',
food: 'beef',
}
}
function deeply(obj) {
let newP = obj instanceof Array ?[]:{} //判断是什么数据类型
for (let item in obj) {
//如果是对象,则遍历到了属性like,则进行递归操作,否则,直接进行赋值操作
if(obj.hasOwnProperty(item)){
newP[item] = obj[item] instanceof Object ? deeply(obj[item]):obj[item]
}
}
return newP
}
let deepPerson = deeply(person)
person.age = 19
person.age.sport = 'swimming'
console.log(deepPerson) //{ name: 冰墩墩', age: 18, like: { sport: 'running', food: 'beef' } }
- obj.hasOwnProperty(prop) 这个方法可以用来检测一个对象是否含有特定的自身属性,和 in 运算符不同,该方法会忽略掉那些从原型链上继承到的属性。