Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
What is the advantage of creating instances from a method rather than constructor?
Take the newly Temporal.PlainDate
class as an example. New instances can be created via the constructor:
new Temporal.PlainDate(year, month, day)
new Temporal.PlainDate(year, month, day, calendar)
or via the from()
method:
Temporal.PlainDate.from(info)
Temporal.PlainDate.from(info, options)
I can see that the arguments are different, but one can make the constructor accept both types. So why isn't it the case? Why having a separate method to create new instances?
1 answer
There are at least two reasons I can see that would motivate this decision (and similar decisions generally), but first it pays to read what the documentation says.
Quoting the pages you reference we have:
This constructor allows you to create instances by directly supplying the underlying data. Like all other Temporal classes, you should usually construct Temporal.PlainDate objects using the Temporal.PlainDate.from() static method, which can handle a variety of input types.
And in the example on that page we have:
// Note that the date is stored internally as ISO 8601, even when it's
// interpreted in a different calendar system. For example, even though
// 2021-07-01 is 4658-05-22 in the Chinese calendar, you still pass the
// ISO date to the constructor.
In other words, the constructor is a low-level interface that is not intended for typical use. The from
function is the intended way to create an instance of this class for most users and use-cases.
So the first thing this separation does is it moves much of the complexity of the from
method out of the base constructor. This means internal (or low-level external) functions don't have to constantly pay the overhead of from
. For example, incrementing the day involves creating a new Temporal.PlainDate
object, but it can be implemented entirely in terms of ISO 8601 operations on the components and doesn't require any complicated calendar translations.
In general, I think there's been a move away from having "overloaded" JavaScript functions that change their behavior based on their arguments. One thing pushing in that direction is the rise of TypeScript and similar tools that benefit from clear, simple types. Even in JavaScript itself, these "overloaded" functions tend to turn what might be (run-time) type errors into just arbitrary behavior. Writing such all-singing all-dancing functions also tends to be error-prone in itself.
In this particular case, it's very clear that it would be extremely confusing for new Temporal.PlainDate(year, month, day, calendar)
to do something totally different from new Temporal.PlainDate({year, month, day, calendar})
. It would also be very confusing for new Temporal.PlainDate(year, month, day, calendar)
to not mean the date represented by that year, month, and day in the given calendar, but instead the ISO 8601 date regardless of calendar
. Again, the constructor is simply not meant to be the "public face" of this class.
0 comment threads