JS数组和对象的深拷贝方法


一、JS 的变量存储方式

在学习JS数组和对象的深拷贝方法前,我们必须了解JS的变量存储方式,这样才能更好的了解深浅拷贝!

JS 的变量存储方式: 栈(stack)和堆(heap)。
栈:自动分配内存空间,系统自动释放,里面存放的是基本类型的值和引用类型的地址(指针)。
堆:动态分配的内存,大小不定,也不会自动释放,里面存放引用类型的值
例如:

        // 基本类型:赋值 相当于 赋了真正的值
            
		let str_1 = 'abc';
        let str_2 = str_1;
        str_2 = 'def';
        console.log(str_1); // abc
        console.log(str_2); // def
       
		// 引用类型:赋值 相当于 赋了引用类型的地址
		
        let obj_1 = {
            name:'张三'
        }
        let obj_2 = obj_1;
        obj_2.name = '李四';
        console.log(obj_1); // {name: '李四'}
        console.log(obj_2); // {name: '李四'}

在这里插入图片描述

二、数组深拷贝

1.for循环

		var arr_3 = [1,2,3];
        var arr_4 = [];
        for (let i = 0; i < arr_3.length; i++) {
             // 循环追加元素
             // 把每一项的元素追加到arr4的后面
             arr_4.push(arr_3[i]);
        }
        arr_4.unshift(0);
        console.log(arr_3); // [1, 2, 3]
        console.log(arr_4); // [0, 1, 2, 3]

2.slice()

		var arr_5 = [1,2,3];
        var arr_6 = arr_5.slice(0);
        // slice() 方法会返回一个新的数组对象
        arr_6.shift();
        console.log(arr_5); // [1, 2, 3]
        console.log(arr_6); // [2, 3]

3.concat()

        var arr_7 = [1,2,3];
        var arr_8 = arr_7.concat();
        // concat() 方法将一个或多个字符串与原字符串连接合并
        // 它会形成一个新的字符串并返回。
        arr_8.pop();
        console.log(arr_7); // [1, 2, 3]
        console.log(arr_8); // [1, 2]

4.filter()

filter 对数组元素进行判断满足条件的会组成一个新的数组

	let clone = (arr) =>arr.filter((x)=>x)

5.使用 ES6 扩展运算符

扩展运算符用于展开数组或对象,可以将一个数组展开为另一个数组。对于数组的深拷贝,可以使用扩展运算符来创建一个新数组,并复制原数组中的元素。

	var newArr = [...arr];

三、对象深拷贝

在 JavaScript 中,实现对象的深拷贝有多种方法。以下是几种常见的对象深拷贝方法:

1.for-in

通过遍历对象中的每一项,把每一项都赋给新对象实现深拷贝

        var obj_1 = {
            name:'张三',
            age:80,
        }
        var obj_2 = {};
        for (const key in obj_1) {
            // 这里的key代表键名
            obj_2[key] = obj_1[key];
        }
        obj_2.name = '李四';
        console.log(obj_1); // {name: '张三', age: 80}
        console.log(obj_2); // {name: '李四', age: 80}

2.JSON.stringify

把一个对象里面的内容转成JSON字符串,再用 JSON.parse() 的方法将JSON 字符串生成一个新的对象。

	var obj_1 = { a: 1, b: [1, 2, 3] }
	var str = JSON.stringify(obj_1);
	var obj_2 = JSON.parse(str);
	console.log(obj_2);   //{a:1,b:[1,2,3]} 
	obj_1.a = 2;
	obj_1.b.push(4);
	console.log(obj_1);   //{a:2,b:[1,2,3,4]}
	console.log(obj_2);   //{a:1,b:[1,2,3]}

3.Object.assign

该方法用于将所有可枚举属性从一个或多个源对象复制到目标对象中,可以用于浅拷贝,但在处理引用类型时仍然存在问题。要实现深拷贝,可以将目标对象设置为空对象,再使用 Object.assign() 复制属性。

	let deepClone = Object.assign({},obj)
    obj.str = 'abc';
    obj.children.str = 'def'
    console.log(obj,'obj');
    console.log(deepClone ,'deepClone ');

4.使用递归实现循环引用处理

在进行对象深拷贝时,循环引用是一个常见的问题,可以使用递归来处理循环引用,通过记录已经拷贝的对象,遇到循环引用时返回已经拷贝的对象。

	function deepCopyWithCircularRef(obj, cache = new WeakMap()) {
	  if (typeof obj !== 'object' || obj === null) {
	    return obj;
	  }
	
	  if (cache.has(obj)) {
	    return cache.get(obj);
	  }
	
	  var copy = Array.isArray(obj) ? [] : {};
	
	  cache.set(obj, copy);
	
	  for (var key in obj) {
	    if (Object.prototype.hasOwnProperty.call(obj, key)) {
	      copy[key] = deepCopyWithCircularRef(obj[key], cache);
	    }
	  }
	
	  return copy;
	}

5.使用第三方库

许多 JavaScript 库(如 Lodash、jQuery 等)提供了深拷贝函数,这些函数可以处理对象的各种情况,包括特殊类型和循环引用。例如,Lodash 的 cloneDeep() 方法可以深拷贝对象。

var newObj = _.cloneDeep(obj);  // 使用 Lodash 深拷贝

需要注意的是,使用某种深拷贝方法时,要考虑对象中的特殊情况和是否需要保留特定对象的原型链。在实际开发中,根据具体的需求和性能要求,选择适合的深拷贝方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

中二病也要写前端

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

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

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

打赏作者

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

抵扣说明:

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

余额充值