总结js实现对象数组的浅拷贝和深拷贝

深拷贝 VS 浅拷贝

深拷贝和浅拷贝都是针对的引用类型,JS中的变量类型分为值类型(基本类型)和引用类型;对值类型进行复制操作会对值进行一份拷贝,而对引用类型赋值,则会进行地址的拷贝,最终两个变量指向同一份数据。

// 基本类型
var a = 1;
var b = a;
a = 2;
console.log(a, b); // 2, 1 ,a b指向不同的数据

// 引用类型指向同一份数据
var a = {c: 1};
var b = a;
a.c = 2;
console.log(a.c, b.c); // 2, 2 全是2,a b指向同一份数据

对于引用类型,会导致a b指向同一份数据,此时如果对其中一个进行修改,就会影响到另外一个,有时候这可能不是我们想要的结果,如果对这种现象不清楚的话,还可能造成不必要的bug

那么如何切断a和b之间的关系呢,可以拷贝一份a的数据,根据拷贝的层级不同可以分为浅拷贝和深拷贝,浅拷贝就是只进行一层拷贝,深拷贝就是无限层级拷贝

浅拷贝的实现方式

方法一:通用循环

function shallowCopy(obj) {
  if (typeof obj !== 'object') return;

  const newObj = obj instanceof Array ? [] : {};

  for(let key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = obj[key];
    }
  }

  return newObj;
}

方法二:Object.assign

let a1 = ['hello', '2018']
let b1 = Object.assign([], a1)
// 改变b1中的值
b1[0] = 'hi'
/**
 * 输出结果发现
 * 改变b1数据
 * a1数组没有改变,b1数组改变
 */
console.log(a1) // ['hello', '2018']
console.log(b1) // ['hi', '2018']
let a2 = [
  {
    name: 'java',
    count: 12
  },
  {
    name: 'js',
    count: 13
  }
]
let b2 = Object.assign([], a2)
// 改变b2数组中其中对象的count值
b2[0].count = 111
/**
 * 输出结果发现
 * 改变了b2数据
 * a1,b1数组都发生了改变
 */
console.log(a2)
console.log(b2)

---输出结果

方法三:Array.slice

var arr1 = ["前端","安卓","苹果"];
var arr2 = arr1.slice(0);
arr2[0] = "后端";
console.log("原始值:" + arr1 );//前端,安卓,苹果
console.log("新值:" + arr2);//后端,安卓,苹果

通过JS的slice方法,改变拷贝出来的数组的某项值后,对原来数组没有任何影响。

缺点:适用于对不包含引用对象的一维数组的深拷贝

方法四:Array.concat

var arr1 = ["前端","安卓","苹果"];
var arr2 = arr1.concat();
arr2[0] = "后端";
console.log("原始值:" + arr1 );//前端,安卓,苹果
console.log("新值:" + arr2);//后端,安卓,苹果

concat方法,原数组和新数组修改某值后,不会改变。

缺点:适用于对不包含引用对象的一维数组的深拷贝

方法五:Array.concat

let arr1 = ['ES6', 'let', 'const']
let arr2 = [...arr1]
arr2[0] = 'JavaScript'
console.log(arr1)
console.log(arr2)

深拷贝的实现方式

方法一:JSON.parse(JSON.stringify())

function cloneJSON(source) {
    return JSON.parse(JSON.stringify(source));
}

方法二:通用循环递归调用

function deepCopy(obj) {
  if (typeof obj !== 'object') return;

  const newObj = obj instanceof Array ? [] : {};

  for(let key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = typeof obj === 'object' ? deepCopy(obj[key]) : obj[key];
    }
  }

  return newObj;
}
function clone(target) {
    if (typeof target === 'object') {
        let cloneTarget = Array.isArray(target) ? [] : {};
        for (const key in target) {
            cloneTarget[key] = clone(target[key]);
        }
        return cloneTarget;
    } else {
        return target;
    }
};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值