js 对象深拷贝_javascript 深拷贝和浅拷贝之如何对一个对象进行深度clone

深拷贝和浅拷贝是针对复杂数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝。

深拷贝

深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。

浅拷贝

浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化。

浅拷贝

可以使用 forinObject.assign、 扩展运算符...Array.prototype.slice()Array.prototype.concat() 等实现浅拷贝。

下面代码使用 Object.assign 实现浅拷贝:

  • 只能保证第一层属性为基本类型String|Number|Boolean|null|undefined|Symbol时,新对象和原来对象互不影响(如:在给 res.name 赋值为'res1'后,test.name 没有改变);
  • 如果第一层的属性是引用数据类型Object|Array|Function|Date|RegExp时,新对象和原对象的属性值指针指向的是同一块内存地址(如:res.arr[0]设置为'res1'后,test.arr[0]也变成'res1')。
const test = {
    name: 'test',
    arr: [1, 2, 3]
};
const res = Object.assign({}, test); // {...test} 相同效果
res.name = 'res1';
res.arr[0] = 'res1';
console.log(test.name);// test
console.log(test.arr);// ["res1", 2, 3]

深拷贝

  • 1.深拷贝最简单的实现是: JSON.parse(JSON.stringify(obj))

JSON.parse(JSON.stringify(obj)) 是最简单的实现方式,但是有一些缺陷:

  • 对象的属性值是函数时,无法拷贝。
  • 不能正确的处理 Date 类型的数据
  • 不能处理 RegExp
  • 会忽略 symbol
  • 会忽略 undefined
  • 原型链上的属性无法拷贝()
function HH () {
        this.hhname = '123';
    }
    HH.prototype.dd = '123';

    var test = {
        name: 'haha',
        date: new Date(),
        height: null,
        width: undefined,
        arr: [1, 3, 4],
        func: function () {                console.log('test.func');
        },
        proto: new HH(),
        mysymbol: Symbol(),
        reg: new RegExp('abc')
    };

    var res1 = JSON.parse(JSON.stringify(test));
    console.log(test);
    console.log(res1);

效果如下

64463bbc17109f733628c298c61ae3bb.png

实现一个 deepClone 函数

var deepClone = (function f (obj) {
        // Date  && RegExp && undefined&&Symbol&&Function&&原型链
        // 判断是否存在
        if (!obj) {
            return obj;
        }
        // 判断是不是Date类型
        if (obj instanceof Date) {
            return new Date(obj);
        }
        // 判断是不是RegExp
        if (obj instanceof RegExp) {
            return new RegExp(obj);
        }
        // 判断是不是null
        if (obj === null) {
            return obj;
        }
        // 判断是不是非对象
        if (typeof obj !== 'object') {
            return obj;
        }
        // 判断是数组还是对象
        var result = obj instanceof Array ? [] : {};
        // 循环
        for (var key in obj) {
            // 判断是不是自身的属性
            if (obj.hasOwnProperty(key)) {
                // 判断是不是对象,因为对象是引用类型,所以需要对引用类型(除了null 这个空对象,null属于基本类型,但是也是对象)再次使用该方法做递归处理
                result[key] = typeof obj[key] === 'object' ? f(obj[key]) : obj[key];
            }
        }
        return result;
    });
    var res2 = deepClone(test);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值