JS is kind of a 'bad language' because:
1) It's missing some pretty important things. Try to determine if a value is a number. Seriously. Look into that mess. Or anything else. Doing simple type-checking is crazy, and we basically are resigned to 'best practices' - which is crazy.
2) Prototype chaining is a neat idea and has some merits - but in reality it makes things super-duper complicated. Ask 10 JS devs how it works and get 21 answers. That is bad.
3) Almost nothing is built in. You need to use a lot of 3rd party libs to do common things.
4) There is no such thing as 'JS' - ever browser, every version - you get completely different implementations. Maybe we can't blame 'JS' - but pragmatically, this means JS is a problem.
A minor issue is issues with packaging, encapsulation and scale, which is also a function of loose typing. When JS programs get complex, they get unruly, and you wish you might be able to do things in an OO language at that point.
JS is really light, and that has advantages - and I think it's the best language for a lot of async things - and UI's are inherently async - so that's good.
In 5-8 years JS might be 'stabilized' in terms of libs or de-facto standards and it will grow.
To anyone who's programmed in other, more established languages, I think it's clear JS has some weirdness that doesn't need to be there.
But I like it.
2) I felt the same way for a while, but recently I was working on something where I ended up really "abusing" the prototype system, and when you actually spend the time to learn it, it's not that bad! It's different, that's for sure, but it's not bad.
I like to think sometimes that if javascript came before C, would we still call many of these things "bad"? Would we call javascript's equality table "weird", or would it be C's that was the weird one? Would C be the star in a talk labeled 'Wat' where they laugh at the absurdity of 'a' == 97? So much of the stuff that people complain about in JS is because they have expectations from other languages. Sometimes those expectations are a good thing, but other times they are just different, and taking the time to actually learn how and why it's different can make you a much better programmer.
3) I genuinely like this about JS. There is no "one true way". The language is free to evolve, change, get new features, get new functionality, and easily "polyfill" old browsers outside of the release cycle. And that's important in JS because there is no one "authority". Keeping the stdlib small means that it's easier for new implementations to crop up, and it leaves the "niceties" to be developed by libraries. It's what allows libraries like ramada and lodash to be so powerful. They wouldn't be where they are today if the stdlib was more opinionated/complete.
4) But again I kind of like this. It does often make things more difficult, but at the same time it improves the ecosystem. I honestly believe that the fact that there are competing implementations is pretty much the only reason javascript (and in some ways, all dynamic languages) are as fast as they are today! Not only that but the fact that there are multiple competing implementations keeps most devs "honest". For the most part I don't need to worry about someone writing code that will run on version X on platform Y. I don't need to worry that the next "update" will require us to spend a week cleaning up removed functionality. It does lead to a lot of "crap" accumulating in the language, but over time that crap can and will be removed. JS is a fluid, constantly-evolving language, and because of that you tend target a point in time, not a "release", and the impressively awesome backwards compatibility means that while your older code might look outdated, it's not going to suddenly stop working.
I do agree that complex JS programs need much more tooling to be manageable, but it's working out very well in my experience. It's just different.