详细介绍js深拷贝与浅拷贝以及如何实现深拷贝

深拷贝与浅拷贝的区别

假如复制A得到了B,如果B中的某个属性发生改变,与此同时如果A中的值也发生改变,叫浅拷贝;

如果A中的值未发生任何变化,叫做深拷贝;

为什么会发生如此变化

主要是因为数据类型的原因

js的数据类型只要分为两大类 基本数据类型(string,number,null,undefined,boolean)与引用类型(object)

深拷贝代码如下

 


// 将obj2的成员拷贝到obj1中, 只拷贝实例成员
function deepCopy(obj1, obj2) {
    for (var key in obj2) {
        // 判断是否是obj2上的实例成员
        if (obj2.hasOwnProperty(key)) {
            // 判断是否是引用类型的成员变量
            if (typeof obj2[key] == 'object') {
                obj1[key] = Array.isArray(obj2[key]) ? [] : {};
                deepCopy(obj1[key], obj2[key]);
            } else {
                obj1[key] = obj2[key];
            }
        }
    }
}

var person = {
    name: 'liyajie',
    age: 25,
    showName: function() {
        console.log(this.name);
    },
    friends: [1, 2, 3, 4],
    family: {
        father: 'ligang',
        mather: 'sizhongzhen',
        wife: 'dan',
        baby: 'weijun'
    }
}
var student = {};
// 将person的成员拷贝到student对象上.
deepCopy(student, person);

深拷贝方式二:

首先我们要理解 JSON.stringify() 是将一个对象序列化为 JSON 的字符串。即把对象变成一个字符串,如

var obj = {
    num:1,
    array:[1,2,3]
}
var str = JSON.stringify(obj);
console.log(str); // "{"num":1,"array":[1,2,3]}"

然后 JSON.parse() 将一个 JSON 字符串解析为原生 js 对象。即把字符串转换为对象,如

var objNew = JSON.parse(str);
console.log(objNew); // {num: 1, array: Array(3)}

这行代码的运行过程,就是利用 JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象;序列化的作用是存储和传输。(对象本身存储的是一个地址映射,如果断电,对象将不存在,所以要将对象的内容转换成字符串的形式再保存在磁盘上)
不过,这种实现深拷贝的方法有局限性,它只适用于一般数据的拷贝(对象、数组),有以下情况需要注意:

1.如果json里面有时间对象,则序列化结果:时间对象=>字符串的形式;

 

{
    let obj = {
        age: 18,
        date: new Date()
    };
    let objCopy = JSON.parse(JSON.stringify(obj));
    console.log('obj', obj);
    console.log('objCopy', objCopy);
    console.log(typeof obj.date); // object
    console.log(typeof objCopy.date); // string
}

2.如果json里有RegExp、Error对象,则序列化的结果将只得到空对象 RegExp、Error => {}

{
    let obj = {
        age: 18,
        reg: new RegExp('\\w+'),
        err: new Error('error message')
    };
    let objCopy = JSON.parse(JSON.stringify(obj));
    console.log('obj', obj);
    console.log('objCopy', objCopy);
}

3.如果json里有 function,undefined,则序列化的结果会把 function,undefined 丢失;

{
    let obj = {
        age: 18,
        fn: function () {
            console.log('fn');
        },
        hh: undefined
    };
    let objCopy = JSON.parse(JSON.stringify(obj));
    console.log('obj', obj);
    console.log('objCopy', objCopy);
}

4.如果json里有NaN、Infinity和-Infinity,则序列化的结果会变成null;

{
    let obj = {
        age: 18,
        hh: NaN,
        isInfinite: 1.7976931348623157E+10308,
        minusInfinity: -1.7976931348623157E+10308
    };
    let objCopy = JSON.parse(JSON.stringify(obj));
    console.log('obj', obj);
    console.log('objCopy', objCopy);
}

5.如果json里有对象是由构造函数生成的,则序列化的结果会丢弃对象的 constructor;

{
    function Person(name) {
        this.name = name;
    }
    let obj = {
        age: 18,
        p1: new Person('lxcan')
    };
    let objCopy = JSON.parse(JSON.stringify(obj));
    console.log('obj', obj);
    console.log('objCopy', objCopy);
    console.log(obj.p1.__proto__.constructor === Person); // true
    console.log(objCopy.p1.__proto__.constructor === Object); // true
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值