浅拷贝和深拷贝

144 阅读2分钟
  • 基本数据类型:Undefined、Null、Boolean、Number、String5种基本数据类型,变量是直接按值存放的,存放在栈内存中的简单数据段,可以直接访问。

  • 引用数据类型: 存放在堆内存中的对象,变量保存的是一个指针,这个指针指向另一个位置。当需要访问引用类型(如对象,数组等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。

首先我们应该思考的是为什么要有深浅拷贝,直接赋值它不香么?

直接赋值

  • 直接赋值存在的问题
  • 把对象赋值给一个变量,那么两者会指向同一个引用地址,其中一方改变,另一方也会相应改变
let foo = {
    name:'宝儿姐',
    quotes: ['社会我宝姐', '专业埋人','埋三送一'] 
}
let bar = foo
bar.name = 'aaa'
bar.quotes = []

console.log(foo)  // {name: "aaa", quotes: []}
console.log(bar)  // {name: "aaa", quotes: []}

浅拷贝

  • 如果想拿到跟别人一模一样的数据,但是又不想影响别人的数据,这时候浅拷贝可以满足我们的需------仅限基本数据类型
  • 浅拷贝:对于基本数据类型直接复制一份,对于引用类型则复制其地址,所以浅拷贝有一个问题,虽然基本类型不受影响,但是修改引用数据类型依然会影响原有的引用数据类型
  • 通过 Object.assign()或者展开运算符可以实现
let foo = {
    name:'宝儿姐',
    quotes: {
      title: '社会我宝姐/专业埋人/埋三送一'
    }  
}
let bar = Object.assign({}, foo)  // 或者 let bar = {...foo}
bar.name = 'aaa'
bar.quotes.title = '社会宝儿姐,人美路子野'

console.log(foo)  // {name: "宝儿姐", quotes: {title:'社会宝儿姐,人美路子野'} }
console.log(bar)  // {name: "aaa", quotes: {title:'社会宝儿姐,人美路子野'}}

深拷贝

  • 不管是基本数据类型还是引用数据类型,原对象和拷贝对象都不会互相影响
  • 通过 JSON.parse(JSON.stringify()) 实现
  • 存在的问题:1、会忽略 undefined 2、会忽略 symbol 3、对于正则表达式类型、函数类型等无法进行深拷贝
let foo = {
    name:'宝儿姐',
    quotes: {
      title: '社会我宝姐/专业埋人/埋三送一'
    }  
}
let bar = JSON.parse(JSON.stringify(foo)) 
bar.name = 'aaa'
bar.quotes.title = '社会宝儿姐,人美路子野'

console.log(foo)  // {name: "宝儿姐", quotes: {title:'社会我宝姐/专业埋人/埋三送一'} }
console.log(bar)  // {name: "aaa", quotes: {title:'社会宝儿姐,人美路子野'}}
两对象是否指向同一内存地址 原基本数据类型是否被影响 原引用数据类型是否被影响
赋值
浅拷贝
深拷贝