It is extremely performant for a scripting language, it is easy to debug, and it works in many scenarios.
People try too hard to be contrarian. Same thing happened with PHP and many other languages.
More specifically, a few things that I think are pretty bad off the top of my head:
- Implicit type coercion
- Confusing scope binding, i.e., `this`, `bind`, etc.
- Inconsistent Array API — some methods return a new value; some methods mutate the value![0]
- `['1', '7', '11'].map(parseInt)` …lol?!
Maybe you shouldn't be so quick to jump to this conclusion that any criticism of your pet technology comes from a place of ignorance or pretension.
[0]: I've actually spoken with Brendan Eich about this one, and he conceded it wasn't a good idea. IIRC, he was just copying what Perl did.
Maybe your argument just isn't that great?
I mean - look, I've worked in a LOT of languages now in the 25 years I've been writing code. Js is certainly no bastion of language perfection, but it's also sure as fuck not on shaky foundations.
Almost all of your criticism basically boil down to: JS won't break backwards compatibility for me! WAHHHHH!
Because none of your examples are really issues:
- Implicit type coercion.
happens in a lot of languages - keep a table around if you need it.
- Confusing scope binding, i.e., `this`, `bind`, etc.
this is literally core to the language - it's not any more confusing than learning about the difference between class definition vs an object instance.
- Inconsistent Array API — some methods return a new value; some methods mutate the value![0].
This is a fair complaint - but all the functions that mutate have non-mutating versions now - JS just won't break compatibility for you by removing the old ones... "WAH!")
- `['1', '7', '11'].map(parseInt)` …lol?!
You know damn well what you're doing Mr radix. Variadic languages have some edge cases. If you don't like it, use Number like a sane person:
['1', '7', '11'].map(Number)
ParseInt is usually not what you want, but again... JS won't break compatibility for you - that doesn't mean the foundation is shaky...
It just means that some parts are older than others.
The fact JS has very limited interaction between threads makes a JIT much easier to write.
In terms of design there’s a lot of annoying things round equality, operators, and coercion which makes everything just that little bit harder to keep in your head. The standard library also has a bunch of inconsistencies in the way it works. I work on a JS implementation every day and I’m always referring to the spec to double check odd corner cases.
I think the choice of double as the only original numeric type has caused a lot of confusion too, even though I’m not in the camp that says you should never use floats.
And easier for developers to write and reason about. This is not small thing. Re-entrant code by default (and basically by mandate) eliminated deadlocks in even a beginner's code. Do you understand how amazing a language is than encourages concurrency and allows parallelism with any fear of deadlocks or explicit atomism?
The reason I mentioned the concurrency model making the JIT easier is that the concurrency model makes it easier to manage the replacement of methods on the stack when an assumption has been invalidated, and this helps with the speed of the compiled code. The same also applied to various languages with green threads or global locks, but outside the JS world being able to use multiple cores has proved more useful than the difference in single threaded code.