There is a growing sentiment among developers that the community is saturated with frameworks that all promise to fix “JavaScript problems”. Some are just frustrated with the high number of frameworks available, but there is also the DIY crowd that opposes any form of JavaScript frameworks. I personally fall somewhere in the middle since I would love for JavaScript to be natively “self-sufficient”, but the current state of the language is just not there yet.
Evolving JavaScript has been a really slow process, but as the only language supported by all browsers, knowing JavaScript has become a necessity for web developers. In recent years it has become a skill set on the server as well. Some will say JavaScript on the server is a joke, but I would argue that JavaScript has features that makes it really shine on the server. I am of course talking about the great asynchronous properties of the language that are very well suited for high traffic websites.
Back to the client. Developers biggest gripe with JavaScript in the browser has traditionally been great variations in implementation between different browser vendors and versions. This has led to miles of browser specific code and targeting. The fix for this problem has for several years now been called jQuery.
However, JavaScript browser support has normalized and the problem described above is more or less just a problem for projects targeting older browsers. Does this mean the need for JavaScript frameworks is gone? My take on this is no. Among other things, JavaScript lacks a native way to do UI composition without tight coupling between DOM and code. This tight coupling ends up hurting testability and separation of concerns since code and DOM are so inseparable. Several new frameworks have popped up in response to this, and we might be at a point where there are too many, but still JavaScript does not have an elegant way to support this natively. A common complaint from the DIY crowd is that frameworks are overkill and complicate the simplest things. This may be true for a lot of cases, but it's also true that a lot of common use cases are supported out of the box by the frameworks. Features that come to mind are databinding, routing, http abstraction and dependency injection. I think a lot of people underestimate the effort involved in creating these features from scratch. Rolling your own implementation of this will also shift focus away from your actual domain problem. Keep in mind, this doesn't stop at initial development since you have to maintain all of your custom framework code going forward as well. Simple projects may not need these features, but if you are building a SPA, chances are you will need most of them.
Another category of JavaScript “helpers” are Transpilers. These are tools outside of JavaScript that add extensions by introducing high level constructs that currently don't exist natively in JavaScript. The transpilers are a layer on top of JavaScript that uses its own syntax that is translated by the tool to regular JavaScript. One downside of this approach is that you have to learn the specific syntax of the transpiler you are using. Some of these tools, like TypeScript, are forward thinking and target proposed definitions of planned extensions to JavaScript.
JavaScript is known for its quirks and weird edge cases. Skilled developers are aware of the many gotchas related to comparison, hoisting etc. However, if you want to eliminate bugs stemming from these weird quirks you may want to add a static analysis tool to your dev environment. The tool is configurable and will scan your code for unwanted code (e.g. == vs ===) and alert you if found. JSHint is an example of a popular static analysis tool.