重新理解深浅拷贝

本文详细解读了JavaScript中的数据类型划分,介绍了浅拷贝与深拷贝的概念及其区别,通过实例演示了浅拷贝(如Object.assign和Array.prototype.concat)和深拷贝(递归实现与JSON.parse/JSON.stringify)的实践应用。特别强调了在复杂数据结构中的浅拷贝陷阱。
摘要由CSDN通过智能技术生成

一、数据类型

js数据类型分为基本数据类型和引用数据类型

基本数据类型(直接存储在栈中的数据):bool,number,string,null,undefined,Symbol

引用数据类型(直接存储在堆内存中的数据):array,object等

保存在栈内存的必须是大小固定的数据,引用类型的大小不固定,只能保存在堆内存中。

二、深拷贝与浅拷贝的理解

深拷贝与浅拷贝均针对于引用数据类型

浅拷贝复制指向某个对象的指针,拷贝的数据会因为原数据的改变而改变;

深拷贝会创造复制一个新的对象与被复制的对象一模一样,不会因为源数据的改变而改变。

三、浅拷贝与赋值的区别

        浅拷贝默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。

        赋值两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容。

四、深拷贝

1.递归拷贝

 // 定义一个深拷贝函数  接收目标target参数
function deepClone(target) {
    // 定义一个变量
    let result;
    // 如果当前需要深拷贝的是一个对象的话
    if (typeof target === 'object') {
    // 如果是一个数组的话
        if (Array.isArray(target)) {
            result = []; // 将result赋值为一个数组,并且执行遍历
            for (let i in target) {
                // 递归克隆数组中的每一项
                result.push(deepClone(target[i]))
            }
         // 判断如果当前的值是null的话;直接赋值为null
        } else if(target===null) {
            result = null;
         // 判断如果当前的值是一个RegExp对象的话,直接赋值    
        } else if(target.constructor===RegExp){
            result = target;
        }else {
         // 否则是普通对象,直接for in循环,递归赋值对象的所有值
            result = {};
            for (let i in target) {
                result[i] = deepClone(target[i]);
            }
        }
     // 如果不是对象的话,就是基本数据类型,那么直接赋值
    } else {
        result = target;
    }
     // 返回最终结果
    return result;
}

2.JSON.parse(JSON.stringify()) 

	let obj = {name:'前端',data : { name1 : 'vue', name2 : 'react'} };
	let obj_json = JSON.parse(JSON.stringify(obj));
	console.log(obj === obj_json);
	obj.data.name1 = "java";
	console.log(obj);//结果为:{name:'前端',data : { name1 : 'java', name2 : 'react'} };
	console.log(obj_json);//结果为:{name:'前端',data : { name1 : 'vue', name2 : 'react'} };

五、浅拷贝

1.Object.assign()

    let obj = { a: {a: "java", b: "python"} };
    let obj_copy = Object.assign({}, obj);
    obj_copy.a.a = "js";
    console.log(obj.a.a); //js

2.Array.prototype.concat() 

	let arr = [1, 3, {name: 'java'}];
	let arr2=arr.concat();    
	arr2[2].name= 'js';	
	console.log(arr);//结果为:[1, 3, {name: 'js'}];

 六、误区

        使用扩展运算符或循环遍历赋值如果循环拿到基本数据类型赋值即为深拷贝,eg:一维简单数组遍历赋值;若为对象或者复杂数据类型遍历赋值为浅拷贝

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值