I'm creating objects with lots of properties and I'm curious about best practices for instantiating them. It seems like it's pretty bad to have really long constructors (instantiating new objects is not fun).
function Book(title, author, pages, chapters, publisher, datePublished, authorHometown, protagonistFavoriteColor) {
this.title = title;
this.authorpages = authorpages;
this.pages = pages;
this.chapters = chapters;
this.publisher = publisher;
this.datePublished = datePublished;
this.authorHometown = authorHometown;
this.protagonistFavoriteColor = protagonistFavoriteColor;
}
// not reliable to remember how to order params
var rc = new Book("Robinson Crusoe", "Daniel Defoe", 342, 16, ...);
I'm wondering if perhaps I should just set maybe three important properties in the constructor (e.g.title, author, and pages) and write individual setters for the rest. Or for consistency should I only use setters? If setting this way is the best path to follow, is there a good way in JS to mandate that those methods be called (kind of like interfaces in Java)?
function Book (title, author, pages){
this.title = title;
this.author = author;
this.pages = pages;
this.chapters = null;
this.publisher = null;
this.datePublished = null;
this.authorHometown = null;
this.protagonistFavoriteColor = null;
}
var rc = new Book("Robinson Crusoe", "Daniel Defoe", 342);
rc.setChapters(16);
rc.setPublisher("John Smith Co.");
rc.setDatePublished("04-25-1719");
rc.setAuthorHometown("London");
rc.setProtagonistFavoriteColor("lilac");
// we'd also want to mandate that these setters be called so nothing is left null
Lastly, would passing in an object to my constructor and destructuring it total defeat the pt of a constructor?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With