Just a side note about your builder pattern example:
Your example does not really fit into the builder pattern: A "builder" should have a function build() (sometimes called get() or construct()) which returns a new object of the target class.
In your example, the instance itself appears to provide builder functions (source("source") etc.). This has many drawbacks: The object can be in an arbitrary state during execution and you need to put a lot of effort into checking the state of the object whenever another part of the program calls a function of that instance. Furthermore, this defaces the public API of your class by mixing instance and builder functions. It makes debugging harder and your code less readable.
If you have a class LeadImporter, you could create a LeadImporterBuilder which provides functions to actually build an instance of LeadImporter (that's why we call it the builder pattern). The LeadImporter should therefore be created
In modern JavaScript, options objects are far more popular. In JAVA, the builder pattern is great, but JavaScript is dynamic enough not to enforce such verbosity. In fact, I can remember very few to none actual uses of the builder pattern in JavaScript.
In JAVA, the builder pattern is very common and a great idea. If you need to configure many properties of an instance, it is much better than invoking a constructor with a lot of unnamed parameters. It is also more flexible by providing the possibility to use multiple varargs arguments in different builder methods. Additionally, the values can still be final within the instance of the resulting class. Another advantage is that some parameters might be optional and it is much more convenient not to call the according builder functions instead of passing null to the constructor of the class itself or creating multiple constructors, depending on the arguments you might want to pass.
Let's look at those four arguments in JavaScript and the alternative options object:
- There are no unnamed parameters. In an options object, every parameter gets a name. Instead of
.source("abc"), you can simply use source: "abc".
- Varargs in JavaScript are something totally simple. But they are unnecessary with an options object because you can just pass an array within the options object. Use
files: [ 'a', 'b', 'c' ] instead of files('a', 'b', 'c').
- You can still make properties "final" with the options object, just configure them not to be writable. However, the concept of "final fields" does not exist in JavaScript. Does not really matter, it is still possible to create immutable objects, even using the options object.
- Simple: Instead of not calling a function, don't pass an option through the options object.
In my opinion, the builder pattern has no advantages over an options object -- at least in modern in JavaScript.