如何在JavaScript中使用箭头函数克隆对象?

the*_*rns 6 javascript scope clone deep-copy

我有这段JavaScript代码:

class Foo {
    constructor() {
        this.b = 1;
        this.getB = () => { return this.b; };
    }
}

const normalFoo = new Foo();
const clonedFoo = magicClone(normalFoo);

clonedFoo.b = 5;

console.log(clonedFoo instanceof Foo); // should be true
console.log(clonedFoo.getB()); // should be 5
Run Code Online (Sandbox Code Playgroud)

我想知道我可以替换什么magicClone以获得所需的结果(例如,一个尊重箭头功能绑定的克隆).

我对任何类型的可怕黑客都很好,只要他们在这种情况下工作,我也可以使用大多数时间都有效的解决方案.这主要是为了我的启发:)


请不要将此问题作为副本关闭 - 克隆对象已被多次询问,但我找不到单一的答案.Object.assign,lodash cloneDeep,jQuery的克隆等都不处理这种情况.

CRi*_*ice 1

因此,这里的主要挑战是您有一个箭头函数被分配为实例的属性Foo。由于箭头函数this从其封闭上下文继承,并且一旦创建就无法反弹getB,因此引用克隆字段的唯一方法b是重新创建该箭头函数。这意味着你必须以某种方式调用Foo构造函数,以便使用正确的上下文重新创建箭头函数。

也就是说,这个magicClone实现可以解决这个例子的问题:

function magicClone(obj) {
    // Manually create new instance of whatever `obj` is by invoking its constructor:
    const newInstance = new obj.__proto__.constructor()

    // Assign to the new instance all the non-function properties of `obj`.
    Object.assign(newInstance, JSON.parse(JSON.stringify(obj)));

    return newInstance;
}
Run Code Online (Sandbox Code Playgroud)

然而,这种方法的主要缺点是,如果obj的构造函数需要任何参数,您无法知道它们应该是什么。因此,这种方法依赖于您的示例类具有无参数构造函数的事实Foo。但如果你能保持在这个限制之内,它确实会给你带来正确的输出:

function magicClone(obj) {
    // Manually create new instance of whatever `obj` is by invoking its constructor:
    const newInstance = new obj.__proto__.constructor()

    // Assign to the new instance all the non-function properties of `obj`.
    Object.assign(newInstance, JSON.parse(JSON.stringify(obj)));

    return newInstance;
}
Run Code Online (Sandbox Code Playgroud)