Javascript中的深浅拷贝

184 阅读2分钟

我们在面试中会经常碰到深浅拷贝的问题,那么它是如何实现的呢?

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的指针指向同一个对象,当对象被修改时,都会受到影响。

``

QQ截图20220211153540.png

  • JSON.parse()和JSON.stringify() 可以用来深拷贝一个对象
  1. JSON.stringify():把一个js对象序列化为一个JSON字符串
  2. 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 运算符不同,该方法会忽略掉那些从原型链上继承到的属性。