I was quite against adding the class keyword to begin with to be honest.
Think a lot of that came at the tail end of the "JavaScript is terrible" generational mentality, and the idea was to copy other languages rather than improve what they had independently.
To be clear, having additional functionality is fine in and of itself, but now the waters are mudied between function oriented and class oriented approaches, and by and large community seems to be settling on function oriented.
In the end, class just created unnecessary fragmentation.
Is it more readable? Yes.
Do I feel like we are dumbing JS down? Yes.
Is it worth it when we consider that it helps onboarding hundreds of thousands of developers who want to choose JS? Oh f* yes!
Or you can simply separate out functions into utility objects rather than attaching to the specific data object, and performance should be the same as using prototype, without any of the special syntax
This model of programming is also much simpler, I'd argue. There is no use of "this", everything is explicit. Especially in JS, "this" sucks because the semantics change depending on whether you use function declarations or arrow functions. And "this" will also reference the caller, so changes if the function gets passed around. Much more obvious to pass an explicit argument to a function than to rely on "this"
I do agree there are use cases where prototypes are more useful, performance sensitive games/server code etc. But pretty rare that you can't take one of the approaches described above. And people writing performance sensitive code aren't generally also going to be the newbies. Additionally, could have had syntax sugar for functions that wired prototype without the new/class paradigm, which I argue just adds unnecessary verbosity to the language.
Also I should mention that in the rare case when I did use the prototypes, I always used the adapter pattern (an adapter function that takes a slice of "this", calls an independent function, and merges it back to "this"), it was easier to test.
But people are so unused to declaring dependencies as parameters (even function dependencies aka services), they cry untestable whenever they see independent (static) functions. I know this from the PHP, Java and .NET world. To this day, it didn't help to explain what they call DI is just passing parameters (but rather more bureaucratically).
But contrary to what you're saying, most popular userland libs are indeed function oriented, and they don't end up like you're suggesting. E.g. RxJS, lodash
By function oriented in this context, I mean that they don't rely on the new keyword for ordinary code. Which reads cleaner
Anyway, functional stdlib can be pretty clean, such as something like Stream(persons).filter(person => person.age > 18).map(person => person.firstName).
Also there's the Pipes spec in the works that would allow for chaining distinct functions that are not on same obj. Not sure of current status
functional stdlib can be pretty clean, such as something like Stream(persons).filter(person => person.age > 18).map(person => person.firstName)
I see a stream object with at least a couple of methods, how is it functional? What does functional mean here, callbacks? I mean, array.filter(predicate) also takes one. If that’s the thing, nobody takes it away, it’s already natural to js, since it’s multiparadigm. And we already have piping, it looks like foo().bar().baz() or map(foo).filter(bar) or Object.keys().reduce(quux). If you want a class deconstructor for FP-101 code, here it is:
const fize = (name, …args) => (obj) => obj[name].apply(obj, args)
array.map(fize("toString", "hex"))
You can turn it into “fize.toString("hex")” with a little Proxy magic (still no chance for a type safety, sadly).I understand the different approaches you propose, and I could even write some decent Haskell in my experimenting ages, but my main question is what problem do we solve here and how this solution would be functional and not “move methods to same-named pojos, write them explicitly and pretend it’s FP”.