As for me, I've only recently entered the JavaScript game, but the php I've seen has been much, much worse. I find the quality of JavaScript I typically encounter is on-par with typical Python code, and a fair bit better than the Frankenstein monsters of dev-ops code that often has a different convention for each line of bash (with attendant third-party applications) mixed in with inscrutable environment states as you shift in and out of various orchestration layers that have zero sense of application hierarchy or even running processes.
I've seen scientific codebases too, but the thing you're getting there is an authorship that is often small-team (1 or 2) and very slow to shift, with highly enculturated domain context. Of course JavaScript code is going to be a mess in organizations where you have devs coming from vastly different contexts and staying a max of 2 years with a team where all you care about is getting the pretty graphic on the screen.
But who is writing it and why they are writing it are inextricably linked with the language. Every language has a culture and a reason for existing, those are pressures that bear as much on the person writing the language and the code produced as much as the person writing the code does on the code and the language.
Whether or not say, modern Java encourages good code is neither here nor there, as not only is there resistance to learning new things there is resistance to using the new things properly. Java has a history of bloated, inefficient code for a reason, and when you use Java, the abstractions you use will alter the code that you write. It's impossible to get away from 'bad code' without rewriting things, and then you're not coding your new project you're rewriting someone else's. It's also 'good practice' to use x y z language idioms, but there are cases when such idioms make the code much harder to read and much less clean.
As an example from C: I like POSIX, but dirname and basename are two ridiculously shit functions. If I choose to use them, the rot starts infesting my code, and everything that deals with them has to account for that, which itself causes a bias towards more obtuse code.
Good languages kinda enforce some kind of basic rules, and prevent developers form making silly mistakes - because we all do them all the time. Those languages usually trade off the performance for safety though.
We should pick the safest language, that prevents errors and mistakes as long as we stay within allowed performance bounds.
JavaScript can be performant, but most of the times it isn't and it isn't safe at all. At least we have typed variants of JavaScript.
JavaScript by design was meant to fail gracefully - in the background - so the site works fine. Sadly nowadays sites are so JavaScript heavy that it isn't helping at all.
I generally prefer statically typed languages just because there is less ambiguity and function definition can help you greatly - you know what you put it, and what it returns.
With dynamic typed languages unless documentation is pristine(and in JavaScript ecosystem it is pretty varied from package to package) you are out of luck unless you look at the implementation.
bash and devOps code has their own special place in hell. bash has only one advantage - it works on any linux distro out of the box, and that's it. It is unreadable untyped mess.
It's the thing that attracts a lot of new beginners who may or may not be interested in the more serious theory that makes programming what it is.
The core data types actually strike a really excellent balance between representing the major distinct paradigms (named collections, unnamed collections, strings, numbers, booleans) while giving you maximum flexibility within them. Its standard library - array functions in particular - has become very mature. FP and OOP concepts are both quite well-supported, and doing async stuff (client or server or otherwise) with promises just smashes every other language I've used in terms of ergonomics.
Much of the above could be said about Python too, but regardless.
TypeScript and Python (with typehints) are the current favorites. Golang seems to be getting up there for me too, but I don't have enough experience with it to actually be able to say that.
There's half a dozen different syntaxes for importing/exporting functions, creating functions, creating objects, etc., and it's all fair game. Then there's the asynchronous nature, so sometimes it's async/await, and sometimes it's promises, and sometimes it's callbacks, sometimes all happening in the same function.
And then on top of that there's all the front-end web frameworks which are like, totally un-opinionated, man, except for the parts where they're implicitly super opinionated.
I imagine that accounts for a lot of bad Javascript and PHP code. By the time I wrote any C++ or Python professionally I had a CS degree and a decade of programing experience.
I'm not saying that a language should only offer one approach to a problem, but there should be general guardrails and guidelines. A shared vocabulary. None of that exists in modern JS
- Bjarne Stroustrup
The fact that we have things like the Wayback Machine is a testament to how this approach, while terrible for developers starting out or working in a legacy codebase, has enabled us to preserve what is now a significant portion of contemporary cultural history. AFAIK there is no similar archive of programs for, say, Java or C.
[1] https://standardjs.com/ [2] https://github.com/airbnb/javascript [3] https://prettier.io/ [4] https://eslint.org/
Semicolons could be considered idiomatic or stylistic, for example. Requiring strict equality operators feels more of an idiomatic way to avoid bugs, rather than simply whitespace. Eslint certainly has a number of rules that are more idiomatic than stylistic.
If you're touching on the lack of consistency in, say, open source javascript, I agree, code is all over the place. Also, I think you're looking at a language that has had dramatically more evolution (especially in recent time) than most other popularly used languages. Old code without promises and suffering from callback hell feels archaic.
However, I think if you look at, say, TypeScript repos (which is cheating, I know, it's not javascript), there is more homogeneity, at least from what I've seen.
Of course it evolved. It’s easy to evolve if it was literally nothing in the first place.
It's like if someone took the BASIC my calculator offered back in the day and turned it into a general purpose programming language.
I wonder how many devs are struggling to debug and fix bad code written using Promise and async features. With care you can use these features safely and productively, but it is also very easy to make subtle mistakes that cause intermittent faults or strange corner case errors.
I would argue that anything for phones is similarly braindead.
While the languages are okay, the API's, UI idioms, and general ecosystem seem to have a half-life of about 6 months. If you step away from programming phones for 18 months, it's like you're learning everything from scratch.
(Side note: All right, Groovy should be taken out and shot and the idiot who foisted it on the Android build system needs to be taken to the woodshed and beaten severely.)
I think your beef there should really be with Gradle, or at least, how it is using Groovy. The way Groovy is implemented as a DSL for Gradle is, in my view, toxic. Almost everything is implicit behavior, crucial aspects rely on totally incidental "magical" features that just make things happen when you invoke some cryptic incantation that has an unobvious connection to its context.
Groovy itself is pretty good and IMHO much better than Java for most purposes.
If you were any good 12 months ago - you will pick up any of the trends quite easily in a week or so (partially because you have also predicted the future).
Well, Python does have strong typing. It's just dynamic, not static, and I've seen enough criticism about it to say that it isn't as unimportant as you make it out to be. JavaScript gets a lot of criticism for having dynamic and weak typing. And I think both forms of criticism are valid, though not everybody agrees, which is fine too.
(I've worked intimately with decades old scientific programming codebases where the scientists didn't give a single damn about writing cleanly and even that was an order of magnitude more readable than the willy nilly, consistency be damned crap I've been seeing in Javascript)
(I feel like I could describe a small portion of hell for me and it would include Javascript)