0

In my app, I'm creating several different objects using data from an API request as follows:

const newRelationship = new Relationship(
    data.id,
    data.account_id,
    data.name,
    data.description,
    data.created_at,
    data.created_by,
    data.deleted_at,
    data.deleted_by,
    data.updated_at,
    data.updated_by,
);

This feels a bit cumbersome. Is there a better (one line) way to do this, rather than writing out all the parameters by hand like this?

I'm hoping for something like below but I'm not 100% on spread/destructuring yet.

const newRelationship = new Relationship(...data);

My Relationship constructor is as follows:

constructor(id, accountId, name, description, createdAt, createdBy, updatedAt, updatedBy, deletedAt, deletedBy) {
    this.id = id || '';
    this.accountId = accountId || '';
    this.name = name || '';
    this.description = description || '';
    this.createdAt = createdAt || '';
    this.createdBy = createdBy || '';
    this.deletedAt = deletedAt || '';
    this.deletedBy = deletedBy || '';
    this.updatedAt = updatedAt || '';
    this.updatedBy = updatedBy || '';
}
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
James Mulholland
  • 1,782
  • 1
  • 14
  • 21

2 Answers2

3

Simplify your constructor to:

const defaults = { id: "", name: "", /*...*/ };

//...

constructor(options) {
 Object.assign(this, defaults, options);
}

Then you can just do:

new Relationship(data)
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • 1
    Instead of specifying defaults externally, I'd opt for destructuring syntax with defaults. Yes you'd have to repeat the properties twice but you'd gain the benefit of not copying parameters that shouldn't be in the class instance. – Patrick Roberts Sep 06 '18 at 23:59
  • @patrick yeah or directly assign them to Relationship.prototype – Jonas Wilms Sep 07 '18 at 07:30
0

If you are writing the class/function (opinion) I would go with object destructuring in the parameters, it makes explicit that you are passing an object to the function and enumerates the properties (you can also rename them if you'd like in the destructure statement). If you are using code that can't be updated on your end I would suggest using array spread with Object.values()

class Relationship {
  constructor({ id, account_id, name, description, created_at, created_by, deleted_at, deleted_by, updated_at, updated_by }) {
    // do stuff with your variables
    console.log(`ID is ${id}`);
  }
}

class OtherRelationship {
  constructor(id, account_id, name, description, created_at, created_by, deleted_at, deleted_by, updated_at, updated_by) {
    // do stuff with your variables
    console.log(`ID is ${id}`);
  }
}

const dummyParams = { 
  id: 1, 
  account_id: 1, 
  name: 'test', 
  description: 'tesssst', 
  created_at: 'some date', 
  created_by: 1, 
  deleted_at: 'some date', 
  deleted_by: 1, 
  updated_at: 'some date', 
  updated_by: 1, 
}

const newRelationship = new Relationship(dummyParams);
const newOtherRelationship = new OtherRelationship(...Object.values(dummyParams))
D Lowther
  • 1,609
  • 1
  • 9
  • 16
  • The order of `values` is not guaranteed. This might cause some really weird and hard to catch bugs. – Yury Tarabanko Jul 11 '18 at 13:46
  • Hmm, that seems to be at odds with the description 'Object.values() returns an array whose elements are the enumerable property values found on the object. The ordering of the properties is the same as that given by looping over the property values of the object manually.'. Is that a known bug? – D Lowther Jul 11 '18 at 13:49
  • 2
    It is not a bug. Objects are "bags of properties" that by spec have no order. The order of properties is up to engine emplementation. It just has to be consistent across `keys`, `values`, `entries`, and `for-in` loops. – Yury Tarabanko Jul 11 '18 at 13:56