浅拷贝和深拷贝理解

有关浅拷贝,深拷贝一直不是很理解,仔细看了一些文档和知识点之后有一些思路和自己的理解,同时还把大学里面学习的知识用到,堆栈,队列等。

js数据类型包括:基本数据类型(Number,String,undefined,Boolean,null),引用数据类型(Array,Object等);浅拷贝,深拷贝是针对引用类型来讲的。

基本类型的名和值都是在栈内存中的,当在赋值时,栈内存都是会新开辟一个内存空间的,所以不存在是不是深拷贝还是浅拷贝。

引用类型的名在栈内存中,值在堆内存中,由栈内存提供一个引用地址指向堆内存中的值,在进行拷贝的时候实际拷贝的是引用地址,并不是实际的值。这时候如果我们想要拷贝值就需要用过浅拷贝和深拷贝。

浅拷贝:复制一层对象的属性,新增了一个新的指针,但是指向了原有的内存地址中,所以如果改变复制的对象时,也会改变原有对象。

常用浅拷贝方法:
1:ES6语法展开运算符…

    const c1 = {
      name: "jack",
      sex: 'man',
      age: 20,
      hobby: ['play', 'swimming', 'study']
    };
    const c2 = { ...c1 }
    console.log(c2, 'c2')

2:Object.assign()
Object.assign() 方法用于对象的合并,将源对象(souce)的所有可枚举属性,复制到目标对象(target)。然后返回目标对象,返回值为合并后的新对象。Object.assign()方法的第一个参数是目标对象,后面的参数都是源对象。
但是Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

注意: 当object只有一层的时候,是深拷贝。

  let obj1 = { username: 'jack' }
  let obj2 = Object.assign({}, obj1)   //将拷贝对象与{}空对象合并
  	  obj2.username = 'mary'
  
  console.log(obj1,'obj1')
  console.log(obj2,'obj2')

3:数组 array.concat()
该方法用于数组合并,合并的数组.concat(被合并的数组…);参数可有多个,用逗号分隔,返回合并后的数组。
原理:用原数组去合并一个空数组,返回合并后的数组。

let arr1 = [1, 3, {
   username: 'jack'
}];
let arr2 = arr1.concat();    
	arr2[2].username = 'mary';
	arr2[0] = 555;
console.log(arr1,'arr1');
console.log(arr2,'arr2');

4:数组 array.slice()
该方法用途很多,可对数组进行增删,剪裁操作。

 const arr1 = [1, 3, { username: 'jack' }]
 const arr2 = arr1.slice()  //返回剪裁后的数组

 arr2[0] = 5
 arr2[2].username = 'mary'

 console.log('arr1', arr1)
 console.log('arr2', arr2)

深拷贝:递归复制所有对象的属性,新增了一个指针的同时申请的一个新的内存地址,让这个新指针指向新的内存地址,所有复制的对象改变之后不影响原对象。

常用的深拷贝方法:
1:使用递归方式实现对数组、对象的拷贝

function deepClone(_obj) {
  //根据isArray方法来判断要拷贝的是数组还是对象,来进行不同的处理
  var clone_obj = Array.isArray(_obj) ? [] : {};
  //判断进行拷贝的是否为空,是否为对象
  if (_obj && typeof _obj === "object") {
    for (key in _obj) {
      if (_obj.hasOwnProperty(key)) {
        // 判断拷贝对象中属性值是否存在,是否为对象
        if (_obj[key] && typeof _obj[key] === "object") {
          clone_obj[key] = deepClone(_obj[key]);// 递归
        } else {
          clone_obj[key] = _obj[key];
        }
      }
    }
  }
  return clone_obj;
}

2:JSON.stringify()和JSON.parse(),来进行对数组的深拷贝,但需要注意,比如拷贝的对象里面含有正则,Date对象,Function等时候,会存在问题,无法拷贝出这些属性。比较好的解决方法是使用valueOf()方法,所有对象都包含此方法。

function deepClone(obj) {
    var _obj = JSON.stringify(obj),
     objClone = JSON.parse(_obj);
     return cloneObj;
}

3:extends方法

var arr = ['a','b','c','d','e'];
var newArr = $.extend(true,[],arr);

4:Object.assign()
当方法中存在多级属性时是深拷贝,只有一级属性是浅拷贝。
5:lodash.cloneDeep()
lodash.cloneDeep()函数库实现深拷贝

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个大土豆的日常

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值