A word of caution - using functional programming principles in a language that is not optimized for it can result in awful performance. In JavaScript, whenever you create a closure it’s a heap allocation. If you’re doing that in a tight loop, it’ll completely dominate the time it takes to run your program.
Redux is a good example of a functional pattern that makes waaay more sense in a language with pattern matching, immutable values, and ADTs built in. You have to really think about what you're doing to scale Redux up with a large app in a JS runtime and to avoid the boilerplate. Last time I used Redux with TS the typings were not particularly helpful as well but that may've improved.
Are you speaking from experience or speculating? It's intuitive that there would be some overhead, but the amount of overhead could be anywhere from tiny to huge, especially given how aggressive V8 is about optimizing certain things
A bit of both. V8 can and will optimize away closures if they can be inlined or they're unused, but it has the additional wrinkle that it's a JIT compiler and we regularly throw megabytes of compressed Javascript at it all while the user is waiting for something to happen. Not an enviable position for a compiler to be in because all analysis and optimization has to be weighed against any potential payoffs and also why I wouldn't rely on the optimizations like you could in an AOT compiled language like Rust or Haskell.
Here are some trivial examples. As you increase the N, the closure containing ones get faster, except the last one (Chrome/M1). I think in real world scenarios the benefits of the optimizations are less clear cut and also the reason why V8 has a reputation for being a bit of a memory hog which is why we should give it a hand and write dumb imperative code.