JavaScript 深复制

JavaScript中对象的深复制

参考资料:

  1. MDN: Object.assign()
  2. 知乎:javascript中的深拷贝和浅拷贝?
  3. 深入剖析 JavaScript 的深复制
  4. js 深克隆(考虑到类型检查,递归爆栈,相同引用,Date和Function等特殊类型克隆,原型克隆)

要理解 JS 对象的深浅复制,首先需要理解:

  • JS 中数据类型分为基本类型和引用类型;
  • 基本类型的比较(赋值)是值的比较(赋值)
  • 引用类型的比较(赋值)是引用的比较(赋值)

参考这篇文章:segmentfault:[ JS 进阶 ] 基本类型 引用类型 简单赋值 对象引用

有了上面的基础,再来讨论对象深浅复制。

基本复制
let me = { name: "zyh", age: "24"};
let meCloned_1 = me;
let meCloned_2 = Object(me);
console.log(me === meCloned_1); // expect true
console.log(me === meCloned_2); // expect true

最基本的复制实际只是实现了引用地址的复制

浅复制
let obj = {
    o: {
        count: 9,
        name: "haha",
    },
    num: 34,
    str: "xixi",
    arr: [3, 9],
}
// let objCloned = deepClone({},obj);
let objCloned = Object.assign({}, obj);

console.log(obj === objCloned); // expect false
console.log(obj.o === objCloned.o); // expect true
console.log(obj.arr === objCloned.arr); // expect true

可以看出来ES6的Object.assign()只能实现对象的浅复制

ES6 Object.assign() 的实现原理如下 deepClone() 函数:

// ES6 Object.assign() 的实现原理如下 deepClone() 函数
            function deepClone(target, varArgs) {
                if (target === null) {
                    throw new TypeError("Cannot convert undefined or null to object");
                }

                let result = Object(target);

                for (let i = 1; i < arguments.length; i++) {
                    let nextSource = arguments[i];
                    if (nextSource !== null) {
                        for (let nextKey in nextSource) {
                            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                                result[nextKey] = nextSource[nextKey];
                            }
                        }
                    }
                }
                
                return result;
            }
            
            let objCloned = deepClone({},obj);
            console.log(obj === objCloned); // expect false
            console.log(obj.o === objCloned.o); // expect true
            console.log(obj.arr === objCloned.arr); // expect true

参考资料:MDN: Object.assign()

深复制

主要参考深入剖析 JavaScript 的深复制

各种深复制方法都存在局限性,没有最好,只有更好

下面是个人实现的深复制函数,仅适用于处理属性值为object和array类型的数据,较为简单,仅供参考

//
            let deepClone = function (obj) {
                if (obj === null) {
                    throw new TypeError("Cannot convert null to object")
                }
                let result = {};
                let flag = Object.prototype.toString.call(obj);
                if (flag === "[object Object]") {
                    for (let key in obj) {
                        if (Object.prototype.hasOwnProperty.call(obj, key)) {
                            let keyFlag = Object.prototype.toString.call(obj[key]);
                            if (["[object Object]", "[object Array]"].includes(keyFlag)) {
                                result[key] = deepClone(obj[key]);
                            } else {
                                result[key] = obj[key];
                            }
                        }
                    }
                } else if (flag === "[object Array]") {
                    result = Array.prototype.map.call(obj, ele => ele);
                } else {
                    result = obj;
                }
                return result;
            }

            let objCloned = deepClone(obj);

            console.log(obj === objCloned); // expect false
            console.log(obj.o === objCloned.o); // expect false
            console.log(obj.arr === objCloned.arr); // expect false
            console.log(objCloned);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值