Javascript has none of the following:
- Macros
- Monads
- call/cc
In fact, most of it was and is written in C/C++, horror of horrors, and fewer in Pascal / Java.
The notable exceptions I can think of are Emacs (partly), Autocad (partly) and Pandoc.
So I guess there's a tradeoff, use cool languages and not contribute much of usable software, or use some so-so language and create stuff people use.
But I don't want to go down the rabbit hole of saying that "TeX & Emacs are somehow more powerful than Chrome because their systems use macros."
Granted, sure. People cope well with not being able to express their problems the way they want to. The existence of so much high-quality C/C++/blub software proves this fact.
But for those of us who don't want to change our thinking, tools that fundamentally extend the language are great to have in our toolbox. Maybe it's our weakness, that we feel uncomfortable when we can't express the problem the way we want. Or maybe it's our strength. I don't know.
True, had TeX itself in mind!
Clojurescript's core.async is a macro approach which is not quite the same but very similar to what I describe.
You could probably do it in sweet.js (marcos for javascript that are expanded at compile time) but as far as I know, nobody is actually doing it so there are probably showstoppers.
A monadic approach requires all of your code to be pure-functional, which is unreasonable because you'd have to rewrite all of your dependencies to be pure.
For monads to work, all your code needs to be pure (in the FP sense). So if you want to do anything substantial with monads in an imperative language, you need to rewrite the entire ecosystem of libraries. That would cost quite a bit more money than your average organization can afford ;)
Lack of purity is a defect which bites you whether or not you have monads: so if you're perfectly happy dealing with it in your existing code base (like most of us are), making explicit the “monadic” patterns in your codebase will not make it worse, and may improve things a bit.
(This is kind of the whole point of monads - you could write a piece of code by composing a few functions, and then make it asynchronous without breaking the function composition! No need to rewrite your code to use callbacks; the same code will just work.)