Equality (and that portion of type coercion) is pretty much solved by using === and the rest of type coercion is solved by only using + when both sides are numbers or strings. I don't see how that gets as much ire as it does
Depending on who you are you can also complain about scoping rules, the object model, semicolon insertion and more general syntactic complaints, speed, access to native APIs and so on. One language is never going to be all things to all people.
I think it means the language forces designs and eventually an ecosystem that's optimized around having cooperative multitasking as the only option. That makes dealing with concurrency an easier task since every library you depend on also takes concurrency seriously. And since cooperative multitasking is much much more efficient than preemptive alternatives, you end up with applications with great efficient concurrency support by default.
E.g. node.js + socket.io. The event-driven concurrency model makes it easier to write servers without worrying about race conditions and thread locks while also having less overhead from a heavy thread implementation. For some applications this has been quite good. The downside is that it can be a bit tricky to scale node.js larger but it's not too hard to run multiple processes or do other load balancing. It's not good for all applications, but very good for some.
> The event-driven concurrency model makes it easier to write servers without worrying about race conditions and thread locks
Well, no, you're just writing the locks yourself in an ad-hoc way. Every time you have a callback calling another callback, you have a lock and all the race condition/deadlock issues associated with that. Of course, writing an application that doesn't have complicated synchronization requirements (streaming fileserver) can often require less boilerplate in an evented system. However, you run into a catch-22 here: by definition it's an application with fewer synchronization requirements, so you'd have to use fewer complicated locks in a 'heavy thread' implementation as well :).
Ultimately it's an engineering tradeoff problem, and you have to weigh lightweight node-style cooperative multitasking with the ability of a traditional thread system to better handle highly complicated scenarios.
Or you can be Russ Cox and argue that this is a false dichotomy and that we should all be using CSP. I'm in that camp.
> makes it easier to write servers without worrying about race conditions
So how do you handle concurrency without race conditions without using isolated processes or pure message passing? Ok so you don't have thread locks, big deal, but you still have shared data structured that could be updated in a non-deterministic order depending on which file descriptor gets fired first by epoll (or whatever select thingy is being used lately).