2

I have a prototype

class Animal() {
    constructor(name, weight) {
        this.name = name
        this.weight = weight
    }
}

and some coming object, which contains these properties plus something else

const obj = {
    name: "name",
    weight: 5,
    someRedundantProp: "bla"
}

I really enjoy JS mapping with Object.assign which would generically create an object for me with all properties, but here I want to fill this new object only with essential fields. Surely, I can map this object like

new Animal(obj.name, obj.weight)

but if at some point I would introduce new properties I will have to change code here, what I don't want to.

Is there some better way?

8
  • constructor(obj) { this.name = obj.name; ... Commented Nov 11, 2017 at 13:35
  • "but here I want to fill this new object only with essential fields" - then define what "essential fields" are. Are they the actual properties the Animal class already "possesses"? Then declare them properly, so that you can loop over them (starting with .hasOwnProperty) to then pick out the input object properties of the same name you'd like to "copy over" Commented Nov 11, 2017 at 13:37
  • @CBroe, essential are fields which constructor expects Commented Nov 11, 2017 at 13:39
  • @JJJ, it can be actually :) Commented Nov 11, 2017 at 13:39
  • I don't understand what you mean. Commented Nov 11, 2017 at 13:41

3 Answers 3

1

You could check if the first argument is an object and then assign the object to this.

But be warned, this has some nasty side effects too.

class Animal {
  constructor( obj ) {
    // Create an object that holds all available options
    const defaultOptions = {
      name: '',
      weight: 0,
    };
    
    // Go over all available options
    Object.keys( defaultOptions ).forEach( key => {
      // Check if obj has key, otherwise use default option
      this[ key ] = obj[ key ] || defaultOptions[ key ];
    } );
  }
}

const obj = {
  name: "name",
  weight: 5,
  someRedundantProp: "bla"
}

const a = new Animal( obj );
console.log( a );

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

3 Comments

well, in this case it will contain all properties, isn't it? including someRedundantProp
Yes. Oh sorry, do you only want to allow certain properties? If so, there might be another good solution available too
I updated my answer. It only takes valid properties now.
1

This should work for you:

class Animal {
    constructor(obj) {
        const defaultFields = {
            name: "",
            weight: 0
        }
        Object.keys(defaultFields).forEach(key => defaultFields[key] = obj[key]);
        Object.assign(this, defaultFields);
    }
}

4 Comments

The reduce looks a little bit of an overkill :) Why not just using forEach and assigning the fields directly instead?
is there a point in creating expectedFields instead of using Object.keys
@VladHatko Where are those keys specified?
I mean, compared to my answer, without rewriting constructor
0

I came to this solution for now

let animal = new Animal()
Object.keys(animal).forEach(field => animal[field] = obj[field])

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.