js深拷贝

49 篇文章 1 订阅

在JavaScript数据类型可以分为8中:字符串(String)、数字 (Number)、布尔 (Boolean)、空(Null)、未定义(Undefined)、Symbol 、Object、BigInt(任意大的整数)

也可以分为基本数据类型、引用数据类型

基本数据类型:字符串(String)、数字 (Number)、布尔 (Boolean)、空(Null)、未定义(Undefined)、Symbol

-----------存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配。

引用数据类型:Object【Object是个大类,function函数、array数组、date日期...等都归属于Object】

-----------存放在堆内存中的对象,在栈内存中存的是一个指针,这个指针指向堆内存一个位置。再从堆内存中取得所需的数据。

区别:

深拷贝:在堆内存中重新开辟一个存储空间,完全克隆一个一模一样的对象。

浅拷贝:不在堆内存中重新开辟空间,只复制栈内存中的引用地址。

本质上两个对象(数组)依然指向同一块存储空间。赋值引用类型的时候肯定不能出现浅拷贝的现象,会对原数据产生影响,那么就要进行深拷贝。

常用的深拷贝方式:

1.JSON.stringify():可以深拷贝的数组和对象,但是不能拷贝undefined和Function类型数据,序列化之后会直接丢失。

    var arr = {
         name: 'lemon1号',
         age: 23,
         foods: ['冰淇淋', '水蜜桃'],
         friend: {
             name: '张三',
             age: '22'
         },
         function(){
             console.log("lemon1号的对象")
         }
     }
    //先转为json格式字符,再转回来
     var _arr=JSON.parse(JSON.stringify(arr))
     _arr.name='lemon2号'
     _arr.adress[0]='大西瓜'
     console.log("arr为", arr)
     console.log("_arr为", _arr)

 2. 封装一个递归方法:这是最保险最推荐的写法。多数第三方库lodash中的cloneDeep()方法底层也是基于的递归。

	    //使用递归实现深拷贝
        function deepClone(obj) {
    		//变量先置空
            let newobj = null;  
            //obj不能为空,并且是对象或者是数组,null也是object
            if (typeof (obj) == 'object' && obj !== null) {
                newobj = obj instanceof Array ? [] : {};
                //递归进行深度的拷贝
                for (var i in obj) {
                    newobj[i] = deepClone(obj[i])
                }
                //如果不是对象直接赋值
            } else {
                newobj = obj;
            }   
            return newobj;    
         }


        //------------------- 使用 ----------------------
        let obj = {
             name: 'lemon1号',
             age: null,
             foods: ['冰淇淋', '水蜜桃'],
             friend: {
                 name: '张三',
                 age: '22'
             },
             function(){
                 console.log("lemon1号的对象")
             }
         }

        const newObj = deepClone(obj); //这样就完成了一个对象的递归拷贝
        newObj.name = 'lemon2号'; 
        console.log(newObj); 

 3.使用扩展运算符:利用了对象的结构赋值特性方法,只能对第一层引用对象进行深拷贝,对于对象中的对象则失效。

    var arr = {
         name: 'lemon1号',
         age: undefined,
         foods: ['冰淇淋', '水蜜桃'],
         friend: {
             name: '张三',
             age: '22'
         },
         function(){
             console.log("lemon1号的对象")
         }
     }
     var _arr={...arr} //这样就完成了一个对象一级拷贝
     _arr.name='lemon2号'
     _arr.friend.name='赵四'
     _arr.foods[0]='大西瓜'
     console.log("arr为", arr)
     console.log("_arr为", _arr)

 4.JQuery的extend()方法进行深拷贝:在JQuery构建的项目中,JQuery自身携带的extend()方法可以进行深拷贝。但是对于undefined类型数据,extend()方法之后会直接丢失。两拷贝对象中有相同的属性名时,后者的值也会覆盖前者的值。

    var obj = {
         name: 'lemon1号',
         age: undefined,
         foods: ['冰淇淋', '水蜜桃'],
         friend: {
             name: '张三',
             age: '22'
         },
         function(){
             console.log("lemon1号的对象")
         }
     }
     let _obj= $.extend(true, {}, obj); //这样就完成了一个对象一级拷贝
     _obj.name='lemon2号'
     _obj.friend.name='赵四'
     _obj.foods[0]='大西瓜'
     console.log("obj为", obj)
     console.log("_obj为", _obj)

总结:在JQuery项目中推荐使用extend()函数,其他项目推荐使用封装的递归函数。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值