浅谈深浅拷贝

一、数据类型

JavaScript 中存在两大数据类型

  • 基本类型
  • 引用类型

基本类型数据存储在栈内存中 储存的是值本身
引用类型数据保存在堆内存中 引用类型的变量是一个指向内存中实际对象的地址

二、浅拷贝

浅拷贝 指创建一个新的数据 这个数据有着初始数据属性值的一份精确拷贝

如果属性是基本类型 拷贝的就是基本类型的值 如果类型是引用类型 则拷贝内存地址

注意点:浅拷贝只拷贝对象的一层属性,如果拷贝是内存地址 两者修改会有影响

简单实现浅拷贝

// 原始:遍历
function shallowClone(obj) {
    const newObj = {};
    for(let key in obj) {
        if(obj.hasOwnProperty(key)){
            newObj[key] = obj[key];
        }
    }
    return newObj;
}

在 JavaScript 中 还可以使用以下方法实现浅拷贝

  • Object.assign
  • Array.concat
  • 扩展运算符
Object.assign
 let obj = {
   name: "赵小童",
   age: 22,
   color: "green",
 }
 let NewObj = Object.assign({}, obj)
Array.cancat
 const arr = [1, 2, 3, 4, 5, 6]
 let newArr = arr.concat([])
扩展运算符
let obj = {
   name: "赵小童",
   age: 22,
   color: "green",
 }
 let NewObj = { ...obj }
 obj.name = "蒋敦豪"
 console.log(obj)
 console.log(NewObj)
 
 // ===========================================
 
 let arr = [1, 2, 3, 4, 5, 6]
 let newArr = [...arr]
 console.log(arr)
 console.log(newArr)
 console.log(arr === newArr)

三、深拷贝

深拷贝会开辟一个新的栈 两个对象属性完全相同 但是对应两个不同的地址 修改一个对象的属性 不会改变另一个对象的属性
深拷贝就是拷贝对象的多层属性 如果对象里面还有对象 会继续拷贝

具体实现方法

  • 使用递归函数遍历
  • 使用lodash库
  • JSON系列化
循环递归
function deepClone(obj, hash = new WeakMap()) {
  if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  // 可能是对象或者普通的值  如果是函数的话是不需要深拷贝
  if (typeof obj !== "object") return obj;
  // 是对象的话就要进行深拷贝
  if (hash.get(obj)) return hash.get(obj);
  let cloneObj = new obj.constructor();
  // 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
  hash.set(obj, cloneObj);
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      // 实现一个递归拷贝
      cloneObj[key] = deepClone(obj[key], hash);
    }
  }
  return cloneObj;
}
lodash库
// 1、先引入lodash库
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.js"></script>
let obj = {
  name: "王一珩",
  age: 18,
  clothes: "东北大花袄",
  car: {
    carName: "大黄蜂",
    carPrice: 9.99,
  },
}
// 2、使用 _cloneDeep方法
let newObj = _.cloneDeep(obj)
consolr.log(newObj)
JSON序列化
const obj2=JSON.parse(JSON.stringify(obj1));

// ================================================
let str = JSON.stringify(obj)
let newObj = JSON.parse(str)
obj.car.carName = "蓝色三轮车"
console.log(obj)
console.log(newObj)

这种方法会有弊端 会忽略undefined 、symbol 和 函数

const obj = {
    name: 'A',
    name1: undefined,
    name3: function() {},
    name4:  Symbol('A')
}
const obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj2); // {name: "A"}

小结:

前提为拷贝类型为引用类型的情况下:

浅拷贝是拷贝一层,属性为对象时,浅拷贝是复制,两个对象指向同一个地址

深拷贝是递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值