如何克隆包含 getter 和 setter 的 JavaScript 对象?

How to clone a JavaScript object including getters and setters?

在我正在进行的项目中,我需要将一个对象克隆到一个变量。

我首先尝试 - 这似乎是最明显的解决方案 - 做 var obj2 = obj1,但我很快意识到这使得 obj2 refer obj1,所以每当我在 obj2 中设置 属性 时,属性 也会在 obj1 中更新。好吧,我不能这样。

所以,我开始四处寻找在 JavaScript 中克隆对象的方法 - 我为此找到了多种解决方案,主要是 var obj2 = JSON.parse(JSON.stringify(obj1)) - 但这并没有保留我拥有的所有 getter 和 setter为我的对象定义!

现在对我来说最明显的解决方案似乎是首先使用上面的 JSON 技巧使 obj2 拥有 obj1 的所有属性,然后遍历所有对象getter 和 setter 并使用 Object.defineProperty() 将它们添加回来,但我还没有找到一种方法来获取对象的所有 getters/setters。

在实际层面上,不可能 100% 准确地克隆一个对象,因为 getter 和 setter(实际上还有其他函数)可能正在通过闭包访问词法范围内的私有变量。访问这样的方法将引用原始对象,而不是克隆对象。

如果(且仅当)不是这种情况,您可以枚举通过 Object.getOwnPropertyNames() 找到的所有属性(甚至是不可枚举的属性),然后为每个名称简单地获取单个 PropertyDescriptorsObject.getOwnPropertyDescriptor 然后将结果字段传递给 Object.defineProperty,例如:

function shallowClone(obj) {
    var clone = Object.create(Object.getPrototypeOf(obj));

    var props = Object.getOwnPropertyNames(obj);
    props.forEach(function(key) {
        var desc = Object.getOwnPropertyDescriptor(obj, key);
        Object.defineProperty(clone, key, desc);
    });

    return clone;
}

在 ES2017 中你可以 do this instead:

function shallowClone(obj) {
    return Object.create(
        Object.getPrototypeOf(obj), 
        Object.getOwnPropertyDescriptors(obj) 
    );
}

来自@Alnitak,我认为这是捷径

function shallowClone(obj){
 var clone = Object.create(Object.getPrototypeOf(obj));
 var descriptors = Object.getOwnPropertyDescriptors(obj);
 Object.defineProperties(clone, descriptors);
 return clone;
}