JS的深拷贝 与 浅拷贝 实例

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指向同一份数据

其实深拷贝和浅拷贝都是针对的引用类型。浅拷贝就是只进行一层拷贝,深拷贝就是无限层级拷贝

例:
(先忽略shadowCopy\deepCopy的具体实现)

var a1 = {b: {c: {}};

var a2 = shadowCopy(a1); // 浅拷贝
a2.b.c === a1.b.c // true

var a3 = deepCopy(a1); // 深拷贝
a3.b.c === a1.b.c // false

一、浅拷贝

//对象浅拷贝
function shadowCopy(obj){
    if(typeof obj !== 'object') return ;
    var newObj;
    if(obj.constructor === Array){
        newObj = [];
    } else {
        newObj = {};
        newObj.constructor = obj.constructor;//保留对象的constructor属性
    }
    for(var prop in obj){
        if(obj.hasOwnProperty(prop)){
          newObj[prop] = obj[prop];
        }
    }
    return newObj;
}
var obj = {arr:[1,2],name:'bty'};
var obj2 = shadowCopy(obj);
console.log(obj.arr[0]);	//1
obj2.arr[0] = 9;
console.log(obj.arr[0]);   //9

上述代码实现了浅拷贝,会有不能正确实现数组的浅拷贝拷贝操作丢失了对象的constructor属性的问题。


二、深拷贝

那么深拷贝可能就需要层层递归,复制对象的所有属性,包括对象属性的属性的属性,有人想出了用JSON的解析实现,如下代码:

function deepCopy(obj){
   if(typeof obj !== "object"){ return ;}
   var str = JSON.stringify(obj);
   return JSON.parse(str);
}

上面的方法不适用的条件是

  • 需要考虑把函数,正则等特殊数据类型复制
  • 当前对象不支持JSON
  • JSON复制会忽略掉值为undefined以及函数表达式

可以看下面的栗子:

var obj = {
    a: 1,
    b: 2,
    c: undefined,
    sum: function() { return a + b; }
};
var obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj2);//输出:Object {a: 1, b: 2}

这个时候还是要层层递归来不同情况不同分析来考虑的,最终的方案如下:

//对象深拷贝
function deepCopy(obj){
    var newObj = obj.constructor === Array ? []:{};
    newObj.constructor = obj.constructor;
    if(typeof obj !== "object"){ 
        return ;
    } else if(window.JSON){
        newObj = JSON.parse(JSON.stringify(obj));//若需要考虑特殊的数据类型,如正则,函数等,需把这个else if去掉即可
    } else {
        for(var prop in obj){
            if(obj[prop].constructor === RegExp ||obj[prop].constructor === Date){
                newObj[prop] = obj[prop];
            } else if(typeof obj[prop] === 'object'){
                newObj[prop] = deepCopy(obj[prop]);//递归
            } else {
                newObj[prop] = obj[prop];
            }
        }
    } 
    return newObj;
}

var obj = {arr:[1,2],name:'bty'};
var obj2 = deepCopy(obj);
console.log(obj.arr[0]);	//1
obj2.arr[0] = 9;
console.log(obj.arr[0]);   //1

注:Object.assign()是深拷贝

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值