Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does this usage of Object.assign make my clone method work incorrectly?

I’m trying to create an ES6 class that has its own clone method allowing itself to be cloned. This should create a new instance of the class, and copy over all of its public data to the new instance. I’m implementing the class like so:

class TestCloneable {
    constructor(someVal) {
        if (someVal) { this.someVal = someVal; }
    }

    clone = () => {
        const cloned = new TestCloneable(this.someVal);
        Object.assign(cloned, this); // same behaviour for Object.assign(cloned, {...this});
        return cloned;
    };
}

let test1 = new TestCloneable(1);
test1.anotherVal = 2;
let test2 = test1.clone();
test2.anotherVal = 3;
let test3 = test2.clone();

console.log(test1);
console.log(test2);
console.log(test3);

What I don’t understand is why test3.anotherVal is 2. I set it to 3 on test2, then cloned test2. Somehow my usage of Object.assign seems to be causing this to refer back to test1 within the clone method of test2 instead of refering to test2 itself. How can I fix this?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

That’s because this syntax clone = () => { } doesn’t create a method, it creates a property

Use correct syntax and it will work

class TestCloneable {
    constructor(someVal) {
        if (someVal) { this.someVal = someVal; }
    }

    clone() {
        const cloned = new TestCloneable(this.someVal);
        Object.assign(cloned, this);
        return cloned;
    };
}

let test1 = new TestCloneable(1);
test1.anotherVal = 2;
let test2 = test1.clone();
test2.anotherVal = 3;
let test3 = test2.clone();

console.log(test1);
console.log(test2);
console.log(test3);

When you used Object.assign you also copied the clone method including the this context. So next time you run clone this is still pointing to the first object.

Cloning everything except the clone function results in the expected behaviour:

class TestCloneable {
    constructor(someVal) {
        if (someVal) { this.someVal = someVal; }
    }

    clone = () => {
        const cloned = new TestCloneable(this.someVal);
        cloned.anotherVal = this.anotherVal;
        cloned.someVal = this.someVal;
        return cloned;
    };
}

let test1 = new TestCloneable(1);
test1.anotherVal = 2;
let test2 = test1.clone();
test2.anotherVal = 3;
let test3 = test2.clone();

console.log(test1);
console.log(test2);
console.log(test3);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading