1

Suppose I have a javascript class:

class SomeClass {
  constructor() {
    this.field1 = [];
    this.field2 = 0;
    this.field3 = "somestring";
  }

  someMethod(param1) {
    // do some magical stuff
  }
}

At some point I have a need to merge two objects, one of them is of SomeClass type.

const obj1 = new SomeClass();

const obj2 = {
    field1: [1, 2, 3],
    field2: [3, 4, 5],
    field3: "other string"
}

const mergedObj = {...obj1, ...obj2};

Now I have lost the someMethod method in mergedObj variable, throwing a TypeError:

mergedObj.someMethod("amazingparam"); //=> Uncaught TypeError: mergedObj.someMethod is not a function

How can I keep the method definitions?

Edit

To be more clear: I would like to create a new object, keep the obj1 and obj2 as they were.

1
  • 3
    Should both the prototype chains also be "merged"? Or only the first object's inheritance matters? Are only two objects being merged or should this work for an arbitrary number of them? Should the first object remain as it is or is it acceptable to be mutated? Commented May 31, 2022 at 10:53

3 Answers 3

3

You could use Object.assign it will merge it for you but this will mutate your first object so to solve that problem you could create a clone of you first object on the fly using Object.create like this

class SomeClass {
  constructor() {
    this.field1 = [];
    this.field2 = 0;
    this.field3 = "somestring";
  }

  someMethod(param1) {
    console.log('hello')
    // do some magical stuff
  }
}

const obj1 = new SomeClass();

const obj2 = {
    field1: [1, 2, 3],
    field2: [3, 4, 5],
    field3: "other string"
}

let mergedObj = Object.assign(Object.create(obj1), obj2);

mergedObj.someMethod('')

Sign up to request clarification or add additional context in comments.

4 Comments

This works well, but only if you don't mind about mutating obj1. It's not clear to me if that's what the OP wants (if so then they don't need mergedObj, they can just mutate obj1 and then use it), or if they want to keep obj1 as it is but define a new object from merging the properties of obj2 into obj1, which isn't as easy to do.
you are right i hope the op response to know exactly what he want
I edited the question. In short I would like to keep both of the objects unchanged.
I edit the answer, check it again
1

From Josephs answer I worked out a solution.

class SomeAmazingClass{
    constructor() {
        this.var1 = "";
        this.var2 = "";
    }

    someMethod() {
        return this.var1 + this.var2;
    }
}

function mergeToSomeAmazingClass(obj1, obj2) {
    return Object.assign(new SomeAmazingClass(), obj1, obj2);
}

let a1 = new SomeAmazingClass();
a1.var1 = "OldVar1"
a1.var2 = "OldVar2"
a1.newVar3 = "Yay"

let a2 = {
    var1: "NewVar1"
}

let merged = mergeToSomeAmazingClass(a1, a2);
console.log(merged.someMethod());

This keeps the method definitions and keeps the input objects from mutating. Looks a little clumsy, but if there is a better solution I would be happy to see that.

Edit

Updated the merge function.

1 Comment

Just as comment (not as critique) to the OP ... Object.assign accepts/consumes more than just 2 parameters ... thus the function can be written like follows ... function mergeToSomeAmazingClass(obj1, obj2) { return Object.assign(new SomeAmazingClass, obj1, obj2); }
0

Simply make your constructor accept optional parameters:

class SomeClass {
  constructor({field1 = [], field2 = 0, field3 = "somestring"}) {
    Object.assign(this, {field1, field2, field3});
  }

  someMethod(param1) {
    // do some magical stuff
    console.log('SomeClass instance here');
  }
}

const obj2 = {
    field1: [1, 2, 3],
    field2: [3, 4, 5],
    field3: "other string"
}

const obj1 = new SomeClass(obj2);

obj1.someMethod();

console.log(obj1);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.