关于JavaScript的浅拷贝和深拷贝

在 JS 中有一些基本类型像是NumberStringBoolean,而对象就是像这样的东西{ name: 'Larry', skill: 'Node.js' },对象跟基本类型最大的不同就在于他们的传值方式。

var a = 25;
var b = a;
b = 18;
console.log(a);//25
console.log(b);//18

基本类型是按值传递,就像上面那样,修b的值并不会改到a

但对象就不同,对象传的是按引用传值。比如:

var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = obj1;
obj2.b = 100;
console.log(obj1);
// { a: 10, b: 100, c: 30 } <-- b 被改到了
console.log(obj2);
// { a: 10, b: 100, c: 30 }

关系图如下 :

因为引用都指向同一个地址,所以修改obj2的,obj的值也被修改了。这就是浅拷贝。

要避免这样的错误发生就要写成这样:

var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };
obj2.b = 100;
console.log(obj1);
// { a: 10, b: 20, c: 30 } <-- b 沒被改到
console.log(obj2);
// { a: 10, b: 100, c: 30 }

这样就是深拷贝,不会改到原本的obj1。但是这样一个个赋值,对象不复杂的情况下还是可以使用的。若对象很复杂,不推荐这样写。

 

深拷贝的实现算法

步骤1

var person = {
    sex : '女',
    other : {
        height : '175cm',
    }
}

function deepCopy(obj){
    return obj;
}

var obj = deepCopy(person);
obj.sex = '男';
console.log(person);
console.log(obj);

把person传进去deepCopy函数,该函数会返回一个对象给obj。(当然,上面的代码还未实现)

步骤2

var person = {
    sex : '女',
    other : {
        height : '175cm',
    }
}

function deepCopy(obj){
    let copyObj = {};
    for(let i in obj){
        copyObj[i] = obj[i];
    }
    return copyObj;
}

var obj = deepCopy(person);
obj.sex = '男';
console.log(person);
console.log(obj);

打印结果 :

结果貌似可以。但是只是sex是深拷贝,other还是浅拷贝。如 :

var person = {
    sex : '女',
    other : {
        height : '175cm',
    }
}

function deepCopy(obj){
    let copyObj = {};
    for(let i in obj){
        copyObj[i] = obj[i];
    }
    return copyObj;
}

var obj = deepCopy(person);
obj.sex = '男';
obj.other.height = '200cm';  //改成200cm
console.log(person);
console.log(obj);

打印结果 :

所以我们需要判断下,传入的对象是否还有子对象,如果有子对象,则在调用deepCopy函数(递归实现)

var person = {
    sex : '女',
    other : {
        height : '175cm',
        hobby : {
            playGame : '麻将,吃鸡,王者',
            skill : {
                1 : 'ps',
                2 : 'php'
            }
        }
    }
}

function deepCopy(obj,obj2)
{
    let copyObj = obj2 || {};
    for(let key in obj)
    {
        let value = obj[key];
        
        //如果对象还包含子对象,则在调用一次自己
        if(typeof value === 'object')
        {
            copyObj[key] = {};
            arguments.callee(value,copyObj[key]);
        }
        //对象只是普通的值
        else
        {
            copyObj[key] = obj[key];
        }
        
    }
    return copyObj;
}

var obj = deepCopy(person);

//修改obj的值
obj.other.height = '200CM';
obj.other.hobby.playGame = 'none';
obj.other.hobby.skill['2'] = 'node';

//打印
console.log(person);
console.log(obj);

打印结果 :

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值