浅拷贝和深拷贝

js内存结构

栈内存:保存的是基本数据类型 string number boolean undefined null
堆内存:保存的是引用数据类型 Object

在栈内存中: 一个变量保存对象 这个 变量实际上保存的是 地址值
这个地址值可以在堆内存中找到对应的一块空间,而这块空间就是用来存放对象中的数据

如图:
将obj的值 赋值 给 obj2也就是将obj保存的那个地址值赋值给obj2,导致obj和obj2都可以找到同一块内存空间.
操作的都是同一块内存空间,一边修改另一边也会变化

拷贝

浅拷贝

只拷贝一层,更深层的对象只拷贝地址值


let obj = {
  name: '小明',
  age: 2,
  girlfriend: {
    name: '小红'
  }
}

function copy(obj){ // obj是要拷贝的对象(这里称为源对象)
  let newObj = {} // 创建一个新对象
  for(let i in obj){ // i 为obj的每一个属性名
    newObj[i] = obj[i]
  }
  return newObj
}

let obj2 = copy(obj) // obj2浅拷贝obj

console.log(obj2.girlfriend === obj.girlfriend) // true 
/*
  为什么这两个对象的girlfriend还是相等的?
  当for in 循环到 girlfriend 这项时,发生如下情况:
  newObj['girlfriend'] = obj['girlfriend']
  这时obj['girlfriend'] 保存的是一个地址值,将这个地址值赋值给了newObj['girlfriend']
  所以这里出现相等情况 这也就是浅拷贝

  如果obj.girlfriend.name = '小花' , 那么 newObj.girlfriend.name 也为 '小花'
  他们两个的 girlfriend 指向同一块内存空间
*/


深拷贝

拷贝多层,每层数据都会拷贝(回用到递归)

let obj = {
  name: '小明',
  age: 2,
  girlfriend: {
    name: '小红'
  }
}

function deepCopy(obj){
  let newObj = {}
  for(let i in obj){
    if(obj[i] instanceof Object){ // 如果该项为引用数据类型(对象)
      newObj[i] = deepCopy(obj[i]) // 递归再调用本身拷贝这个引用数据,会返回一个新对象
    }else{ // 基本数据类型
      newObj[i] = obj[i]
    }
  }
  return newObj
}

let obj2 = deepCopy(obj) // obj2深拷贝obj

console.log(obj2.girlfriend === obj.girlfriend) // false
/*
  分析:
    当for in 循环到 girlfriend 这项时发生如下情况:
    obj[i] == girlfriend:{xxxxx} 是个对象
    obj[i] instanceof Object // true进入执行代码块
执行代码块:
    newObj[i] = deepCopy(obj[i])
    deepCopy(obj[i]) 会返回一个新的对象
    这个新的对象里面包含了obj[i]也就是obj.girlfriend里的属性
    完成了深层拷贝

这就是深拷贝
*/

还有一种比较简单的实现深拷贝的方法:

// 利用JSON(javascript对象表示法)
let obj2 = JSON.parse(JSON.stringify(obj))
// 先把源对象转换成JSON格式字符串,再解析这个JSON字符串.用一个变量保存
posted @ 2022-07-22 17:33  ycccc丶  阅读(55)  评论(1编辑  收藏  举报
//背景线条