The Conventional Module pattern is usually expressed as a plain object literal with a set of methods:
const timeDiffUtility = {
minutesBetween(dateA, dateB) {},
hoursBetween(dateA, dataB) {},
daysBetween(dateA, dateB) {}
};
It's quite typical for such a module to also reveal specific initialization methods such as initialize, init, or setup. Alternatively, we may want to provide methods that change the state or configuration of the entire module (such as setConfig):
const timeDiffUtility = {
setConfig(config) {
this.config = config;
},
minutesBetween(dateA, dateB) {},
hoursBetween(dateA, dataB) {},
daysBetween(dateA, dateB) {}
};
The Conventional Module pattern is incredibly flexible since it is just a plain object. JavaScript's treatment of functions as first-class citizens (that is, they're just like any other value) means that you can easily compose the objects of methods from functions defined elsewhere, as well:
const log = () => console.log(this);
const library = {
books: [],
addBook() {},
log // add log method
};
Conventionally, you may have considered using an inheritance or mixin pattern to include this log method in our library module, but here we're simply composing it ourselves by referencing and inserting it directly into our object. This pattern gives us a lot of flexibility in terms of how we reuse code in JavaScript.