对象深复制(深拷贝)

664 阅读1分钟
  • 测试用例
class Box {
    static ARG = ["a", "b"];
    constructor(a, b) {
        this.a = a;
        this.b = b;
    }
    play() {
        console.log(this.a + this.b);
    }
}

var obj = {
    a: 1,
    b: "a",
    c: false,
    d: {
        e: undefined,
        f: null,
        g: [1, 2, 3, 4, 5],
        h: new Date(),
        i: /^[a-z]{2,4}$/gi,
        j: new Box(4, 5),
        k: {

        }
    }
}

Object.defineProperties(obj.d.k, {
    l: { value: 10 },
    m: {
        configurable: true,
        writable: true,
        value: 20
    },
    n: {
        enumerable: true,
        value: function () {
            console.log("aaaa");
        }
    },
    o: {
        value: new Image()
    }
})
  • 深复制
function cloneObject(target, source) {
    //Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性
    //性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
    var names = Object.getOwnPropertyNames(source);
    for (let i = 0; i < names.length; i++) {
        //Object.getOwnPropertyDescriptor() 方法返回指定对象上一个
        //属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,
        //要从原型链上进行查找的属性)
        var desc = Object.getOwnPropertyDescriptor(source, names[i]);
        if (typeof desc.value === "object" && desc.value !== null) {
            var obj;
            if (desc.value instanceof HTMLElement) {
                obj=document.createElement(desc.value.nodeName);
            } else {
                switch (desc.value.constructor) {
                    case Box:
                        obj = new desc.value.constructor(desc.value[Box.ARG[0]], desc.value[Box.ARG[1]]);
                        break;
                    case RegExp:
                        obj = new desc.value.constructor(desc.value.source, desc.value.flags);
                        break;
                    default:
                        obj = new desc.value.constructor();
                }
            }

            cloneObject(obj, desc.value);
            //Object.defineProperty() 方法会直接在一个对象上定
            //个新属性,或者修改一个对象的现有属性,并返回此对象。
            Object.defineProperty(target, names[i], {
                value: obj,
                enumerable: desc.enumerable,
                writable: desc.writable,
                configurable: desc.configurable
            });
        } else {
            Object.defineProperty(target, names[i], desc);
        }
    }
    return target;
}
  • 调用测试
var obj1 = cloneObject({}, obj);
obj.d.k.m = 100;
console.log(obj1);