Best Practices for Long Constructors in JavaScript

Best practice would be to pass an object defining properties into constructor:

function Book(props) {
  // create variables out of object (if you need to)
  const {
    title,
    author,
    pages,
    chapters,
    publisher,
    datePublished,
    authorHometown,
    protagonistFavoriteColor
  } = props;

  // assign properties to instance object
  Object.assign(this, props);
}

const rc = new Book({
  title: "Robinson Crusoe",
  author: "Daniel Defoe",
  pages: 342,
  chapters: 16,
  // rest of properties
});

console.log(rc);

JSFiddle Demo: https://jsfiddle.net/Lr6umykn/3/


Seems like it might be best to use an arguments object and a mixin. This is kind of a double edged sword in that it makes the code that instantiates the object easier to read, but the constructor itself a little less obvious. e.g.

function Book(args) {
     Object.assign(this, args);
}

var rc = new Book({
    name:   "Robinson Crusoe",
    author: "Daniel Defoe",
    pages:  342
});

If you want default values, then you can implement that with another mixin e.g.

function Book(args) {
    args = Object.assign(args, {
       protagonistFavoriteColor: "Red"
    });

    Object.assign(this, args);
 }

Then an invocation such as :

var rc = new Book({
    name:   "Robinson Crusoe",
    author: "Daniel Defoe",
    pages:  342
});

Would give :

rc.author; // "Daniel Defoe"
rc.protagonistFavoriteColor // "Red"

If you want to make sure certain values are provided, you would need to test at the end of the constructor that those are present and throw an Error.


In es6 you can use destructuring and Object.assign to simplify the copy constructor pattern (a constructor taking a parameter-laden object as its single argument):

function Book({title, author, pages, chapters, publisher, datePublished,
               authorHometown, protagonistFavoriteColor}) {
  Object.assign(this, {title, author, pages, chapters, publisher, datePublished,
                       authorHometown, protagonistFavoriteColor});
}

var rc = new Book({title: "Robinson Crusoe", author: "Daniel Defoe",
                   pages: 342, chapters: 16});

var copy = new Book(rc);

console.log(JSON.stringify(rc));
console.log(JSON.stringify(copy));
console.log(copy == rc); // false

It's called that, because you can now conveniently create an object from another instance.

We enumerate each property in Object.assign, to assign only valid parameters.

Does this defeat the purpose of having a constructor in the first place? If this is all you class does, then yes. Yes it does. But hopefully your class has some methods and purpose to it other than this.