Objects with instance variables don't automatically mean the state is shared. A JS event loop holding onto a simple object with some data is not practically different from a functional event loop with some big context carried between executions. One will have mutations, the other will do effectively the same with tail call and some IO executor. In both you have to add the shared state explicitly, one just makes it way harder.
> you'll have a hard time finding any relatively popular JS/TS project that doesn't overtly rely on shared state one way or another
That's sampling bias. Where's the thousands of the event driven DOM UI Haskell projects, which doesn't rely on shared state?
> Objects with instance variables don't automatically mean the state is shared.
Agree, but JS's syntax and constructs are almost begging the user to encapsulate their state in classes and instances and share those instances between function calls, rather than passing the data itself around. This is very visible if you browse the various JS APIs as well.
> you'll have a hard time finding any relatively popular JS/TS project that doesn't overtly rely on shared state one way or another
That's sampling bias. Where's the thousands of the event driven DOM UI Haskell projects, which doesn't rely on shared state?