Easy but Complex
Building software in languages like C or JavaScript presents challenges due to their fundamental design.
Key Issues:
Simple Syntax, Hidden Complexity: Basic operations seem easy, but as code grows, managing it becomes complex and cumbersome.
Implicit Behavior: JavaScript often relies on implicit rules, leading to code that does more than it appears, which can cause incorrect assumptions and hard-to-detect errors.
Examples:
Closures: The behavior is implicit; issues might not surface until problems arise.
Hoisting:
var
variables are moved to the top of their scope, which can be confusing.Equality: Differences between
==
and===
can lead to subtle bugs.
Such hidden complexities often cause non-trivial issues that seem fine initially but can lead to significant problems later.
Lack of Standard Library
As the demands on JavaScript developers increase, so does the language's scope. ES2015 marked a major milestone, introducing features that made JavaScript suitable for large-scale projects. However, despite these advancements, JavaScript still lacks many fundamental features offered by other major languages.
Like:
Core library - Java has collections, standard utils, file system APIs etc etc. There is no such thing in JS.
Standard Module system - Think packages in Java. Here we have 3 module standards.
Burden of legacy. Breaking changes are not just feasible here. A small breaking change in the language will break websites across the globe.
Weird core semantics - Enough said?
All these problems have been solved by the community. This is unlike any other language ecosystem.
You want a core library - we have a million.
You want a module system - we have 4.
You want to run it on the server -> we have 5 runtimes.
You want x -> there is a library for it.
Great Community
The lack of standardized features in JavaScript has created space for a thriving ecosystem. These challenges and opportunities are two sides of the same coin.
This gap has fueled an unprecedented surge in open-source software (OSS) and tools, unmatched by any other language.
npm hosts over a billion libraries—the largest repository in the world. This scale is mind-boggling.
JavaScript's ecosystem is like a free market of ideas. The language's core gaps have led to remarkable innovation and sophisticated tools, with performance continuously improving. In this ecosystem, GitHub stars are the currency.
JavaScript's unique qualities contribute to its widespread appeal:
Malleable Core: Highly flexible and adaptable.
Beginner-Friendly: Easy to get started.
Comprehensive Documentation: Resources like MDN make learning accessible.
Immediate Visual Feedback: Great for engaging first-time developers.
…
In JavaScript, imagination is the only limitation.
Beyond Browser - Node, Bun etc
Despite its humble origins in the browser, JS has long come out of this constraint.
The competition in the browser space triggered a lot of innovation in optimizing the JS interpreter. Chrome is the front-runner here. V8 was able to provide performance comparable to that of compiled languages.
That is amazing. As it was open source, folks did what folks do. Some smart folks took the engine and were able to run it outside of the browser.
What we know today as Node.js.
How cool is OSS? It has a life of its own.
Now we have multiple run times each competing for performance. Again free market vibes here.
Compile to JS
JavaScript's open and flexible nature allows it to adapt to almost any need. However, this flexibility comes at a cost:
Complex Codebases: Many projects become tangled and difficult to manage.
Dependency Management: Keeping track of dependencies can be overwhelming, with high costs if neglected.
Inconsistent Libraries: The variety of tools and libraries often lack cohesion, adding friction to development.
To address these challenges, teams need to enforce strict constraints and foster a minimalist approach to dependencies—an inherently difficult task.
Instead of relying solely on JavaScript or TypeScript (TS), consider alternative languages that compile to JavaScript. While TypeScript improves JS development, it still inherits and sometimes amplifies JavaScript's issues due to its quirks.
The languages I would recommend:
ReScript
Integrates well with React.
Easy to adopt incrementally for stable apps with high maintenance needs.
Produces clean, efficient JavaScript.
Elm
Offers minimal maintenance overhead and lower refactoring costs.
Ideal for projects with long-term stability requirements.
Very different from JS but worth considering for its robustness.
ClojureScript: Another excellent option, especially if you appreciate LISP's approach.
Conclusion
JavaScript's open-source ecosystem fosters innovation but also leads to rapid changes and increasing complexity. It's easy to start a project but challenging to keep it manageable over time.
Consider how Rust and Zig offer native compilation without C's pitfalls. Similarly:
Elm is like Rust for JavaScript: stable, safe, and functional.
ReScript is akin to Zig: efficient and practical.
Both compile to clean JavaScript and help avoid its common issues.
(And yes, I lean towards functional programming, so my choices reflect that! 😁)