深浅拷贝总结

目录

一:数据类型

二:拷贝

代码实现浅拷贝

代码实现深拷贝


一:数据类型

  1. 数据类型

    基本数据类型:null,string,undefined,number,Boolean,symbol

    引用数据类型:object对象、Array数组、Function函数。

  2. 两种数据类型的区别

    栈(stack):是自动分配的内存空间,大小固定,内存由系统自动释放。

    堆(heap):是动态分配的内存,大小不一定,会自动释放

    1. 存储位置不同: 基本类型存储在栈中,大小固定,占空间小,是频繁操作的数据。 引用数据类型存储在堆中,占据空间大,大小不固定。

    2. 传值方式不同: 基本数据类型 按值传递,无法改变一个基本数据类型的值

      引用数据类型 应用类型值可以改变

    3. 基本类型的值是不可变的:即任何方法都无法改变一个基本类型的值,我们不能给基本类型添加属性和方法; 引用类型的值是可变的:我们可为为引用类型添加属性和方法,也可以删除其属性和方法。

    4. 比较

      • 基本数据类型的比较是值的比较,只有在它们的值相等的时候它们才相等;

      • 引用数据类型的比较是引用的比较,因为它是按引用访问的,换句话说就是比较两个对象的堆内存中的地址是否相同。

js存储有 基础类型是栈存储,引用数据类型是堆存储。

        //直接赋值
        const initDate = [1 ,{obj:'123'}];
        const finalDate = initDate;
        finalDate[0] = 2;
        finalDate[1] = '456';
        console.log(initDate);//[ 2, { obj: '456'}]
        console.log(finalDate);//[ 2, { obj: '456' }]
​
        // 基本数据类型
        let str1 = '123';
        str2 = str1;
        str2 = '456';
        console.log(str1);// '123'
        console.log(str2);// '456'
​
        // 引用数据类型
        let arr1 = [1, 2, 3];
        arr2 = arr1;
        arr2.push(4);
        console.log(arr1); //[1,2,3,4]
        console.log(arr2); //[1,2,3,4]

例子可以看出:

直接赋值情况下,finalDate也会改变原来的initDate

基本数据类型的拷贝,拷贝的是值,修改str2不影响str1

引用数据类型的拷贝,拷贝的是地址,修改str2会修改str1

二:拷贝

赋值: 修改赋值后的数据,不管是基本数据类型还是引用数据类型,都会影响到原数据

浅拷贝:一层拷贝,拷贝的是地址。在浅拷贝中,修改基本数据类型不会影响原有数据的基本数据类型,修改引用数据类型会影响到原有的数据类型。

深拷贝:无限层级拷贝,拷贝值。在深拷贝中,修改基本数据类型和引用数据类型都不会影响原有的数据类型。

代码实现浅拷贝

1. 循环遍历对象可枚举值

// 手写浅拷贝
const arr1 = [1, 2, ['html', 'css'], 4];
​
const shallowClone = (arr) => {
  const dst = [];
  for (let prop in arr) {
    console.log(prop)
    if (arr.hasOwnProperty(prop)) {
        dst[prop] = arr[prop];
    }
  }
  return dst;
}
​const arr2 = shallowClone(arr1);
arr2[2].push('Javascript');
arr2[3] = 5;
​
console.log(arr1);
// [ 1,2,['html','css','Javascript'], 4 ]
console.log(arr2);
// [1,2,['html','css','Javascript'], 5 ]

for ... in : 遍历object对象arr1 ,将其可枚举值列举出来

hasOwnProperty(): 检查该枚举值是否属于该对象arr1,如果是继承过了的就去掉,如果是自身的则进行拷贝。

2. object.assign()

ES6新增方法,把任意多个源对象自身的可枚举对象拷贝给目标对象,然后返回目标对象

const obj = {
    name : "mingming",
    age : "20",
    skill : {
        read : "html",
        write : "css"

    },
    like : ['yy','zz','mm']
}

const newobj = Object.assign({},obj)

newobj.name = "ss"
newobj.skill.read = "js"
newobj.like = ["ee"]

console.log(obj)  
// { name: 'mingming',
//   age: '20',
//   skill: { read: 'js', write: 'css' },
//   like: [ 'yy', 'zz', 'mm' ] }
console.log(newobj)
// { name: 'ss',
//   age: '20',
//   skill: { read: 'js', write: 'css' },
//   like: [ 'ee' ] }

可以看出,object.assign()拷贝第一层基本数据,完全拷贝,第二次引用类型浅拷贝,拷贝地址。 

3. Array.propotype.concat()

concat()是数组的内置方法,合并两个或多个数组,不会改变现有数组,返回新的数组

4. Array.propotype.slice()

concat()是数组的内置方法,该方法返回一个新的对象,不改变原数组

5. 展开运算符...obj

用const obj2 = {...obj1}方式进行拷贝

代码实现深拷贝

1. JSON.parse( JSON.stringify() )

JSON.stringify() :将对象转为JSON字符串

JSON.parse() : 将字符串解析成对象

 const arr1 = [
    3,
    {
      name:'ww'
    },
  ];
  let arr2 = JSON.parse(JSON.stringify(arr1));
  
  arr2[0] = 2;
  arr2[1].name = 'zz';
  console.log(arr1);
  // [ 3,name:'ww']
  console.log(arr2);
  // [ 2, { name: 'zz' } ]





















教你手撸深拷贝与浅拷贝 | Ahuiyo の Blog

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值