One thing I've struggled with in JavaScript is choosing a more functional or OOP approach in certain situations. I can never tell if I should stick to one or the other. Allonge sounds like it'll really help me figure that out.
> One thing I've struggled with in JavaScript is choosing a more functional or OOP approach in certain situations
A couple key realizations made this much less of a "choice" for me (warning, my opinion):
1. Classes et al, are just a high level pattern which happens to be builtin... functions are far far more rudimentary.
2. If you use a high level pattern "just because you can" without considering the subjective cost vs benefit, it will be a poor fit on average.
What does this mean?
#1 Functions are not the opposites of classes, they are simpler, lower level abstractions which are more generalized - It should be thought of as the default.
#2 Like any pattern, OOP has a cognitive cost - When they don't fit a problem well, they merely obscure relationships between state and function; when they do fit a problem, they will minimize that cost and provide benefits that simplify other code.
If you don't immediately know that classes or prototypes fit the piece of code you are writing... just stick to functions, if later on you find that a collection of functions emerge with a common signature and persistent state being passed back and forth - you might have something that would benefit from a class, but you can simply change them into a class when it emerges. However if you do it preemptively you will probably be wrong and also make poor decisions about what the internal encapsulated state should be (which you want to minimize since you are obscuring it). It's ok to discover that something should be a class, attempting to make the choice up front is usually going to go wrong unless it's very obvious.
I think it's unfortunately a pretty natural path to start out not having an opinion of OOP and then potentially developing a distaste for it later on - not because it's inherently bad (it's probably the most generalized pattern and very useful); but because of it's integration into so many languages... I see it get abused by people all the time who just make a class by default for no apparent reason, which inevitably ends up as a bag of loosely associated state and arbitrary functions mutating one or more of those states. In such cases the class is of no benefit, and worse, it's obscuring all of the unrelated state mutations making it difficult to read and reason about.
The problem here is that this conversation is made complicated by the fact that plain objects in JavaScript are not what is really being talked about when people say the term OOP. So to clarify, stateful classes would be what I am talking about when I use that term. The foundation of OOP is based on tying state with functions in what are deemed "Objects". This implicitly makes all methods in an Object that depend on or modify an Object's internal state impure functions. And the purpose of most Objects methods are for the purposes of doing those things. Basically if you use stateful classes that encapsulate state and modify their own internal state with functions you are not doing functional programming. These two paradigms are in fact at odds and not compatible.
> This implicitly makes all methods in an Object that depend on or modify an Object's internal state impure functions
Note that you can have methods which do not depend on mutable state. In ES6 you can FREEZE objects, which you could do in the constructor. Freeze the object after having set its "instance variables". Now all methods of that object are "pure functions". So you can choose. Choose to create pure functions or impure.
Creating a new immutable instance really is equivalent to creating a set of immutable ('pure' if you like) functions.
How do you define object-oriented programming? From my perspective the very core of it is stateful objects with encapsulation and methods on those objects that pretty much always are not pure. If you just start treating objects like collections of functions, I don't really see how that's OOP. As far as I remember, it has been a little bit since I've used OOP everyday, pretty much every facet of the paradigm is centered around mutating state. You can certainly commingle OOP and functional code, but they simply aren't compatible paradigms.