Why JavaScript Won

Created in ten days, mocked for decades, now everywhere. How a hastily designed scripting language became the most widely used programming language on Earth.

Ten Days in May

In May 1995, Brendan Eich was hired by Netscape with the promise that he could implement Scheme, an elegant Lisp dialect, in the browser. That plan lasted about two weeks. Management wanted something that looked like Java (Sun Microsystems was a partner) but was simpler, a scripting language for designers and part-time programmers. Eich built the first prototype in ten days. It was called Mocha, then LiveScript, then JavaScript, the last name chosen purely for marketing reasons to ride Java's hype wave.

The language Eich created was a strange hybrid. It had C-like syntax (to look like Java), first-class functions (from Scheme), prototypal inheritance (from Self), and a handful of decisions made under extreme time pressure that would haunt developers for decades. Type coercion, the distinction between null and undefined, automatic semicolon insertion, and the peculiarities of "this" binding were all consequences of building a language in less than two weeks.

The Browser Monopoly

JavaScript's initial advantage was simple: it was the only language that ran in the browser. This was not a technical inevitability. Microsoft created VBScript for Internet Explorer. Java applets existed. Flash had ActionScript. But JavaScript had first-mover advantage in the browser and, critically, Netscape gave it to Ecma International for standardization in 1996. The resulting ECMAScript specification meant that any browser implementing the standard would run the same JavaScript code.

The browser wars of the late 1990s and early 2000s were brutal for developers. Internet Explorer 6, which held over 90% market share at its peak, implemented JavaScript inconsistently and added proprietary extensions. Writing cross-browser JavaScript was an exercise in frustration. Libraries like jQuery (2006) existed primarily to paper over browser incompatibilities. For years, "real" programmers dismissed JavaScript as a toy.

Ajax Changes Everything

In 2005, Jesse James Garrett published an essay coining the term "Ajax" (Asynchronous JavaScript and XML). The technique itself was not new. Microsoft had introduced XMLHttpRequest in Internet Explorer 5 (1999), and Google had used it in Gmail (2004) and Google Maps (2005). But the essay gave the technique a name and a narrative. Web applications could update content without reloading the entire page. The browser was no longer just a document viewer. It was an application platform.

This shift changed JavaScript's status overnight. If the browser was an application platform, then JavaScript was not a toy. It was the programming language of the world's most ubiquitous runtime environment. Investment in JavaScript tooling, frameworks, and education accelerated dramatically.

The Framework Era

The Ajax revolution created demand for more structured JavaScript code, and frameworks rushed to fill the gap. jQuery (2006) dominated the first wave by abstracting away browser inconsistencies, but it was a library, not an architecture. The real architectural revolution began with Backbone.js (2010) and AngularJS (2010), which brought MVC patterns to the browser.

AngularJS, backed by Google, was the first JavaScript framework to gain widespread enterprise adoption. Its two-way data binding (changes in the UI automatically updated the model, and vice versa) felt like magic to developers accustomed to manually manipulating the DOM. But it was also slow for large applications, and its "digest cycle" became a performance bottleneck that frustrated developers building ambitious interfaces.

React (2013), created by Jordan Walke at Facebook, changed the game by introducing the virtual DOM: instead of directly manipulating the browser's DOM, React maintained a lightweight copy in memory, computed the minimal set of changes needed, and applied them in a batch. This approach was faster, more predictable, and easier to reason about than AngularJS's approach. React's component model, where UI was built from composable, reusable pieces, became the dominant paradigm for frontend development.

Vue.js (2014), created by Evan You after working on AngularJS at Google, offered a more approachable alternative to React, with a template syntax that felt familiar to developers coming from traditional web development. Svelte (2016), created by Rich Harris, went further by eliminating the virtual DOM entirely, compiling components into vanilla JavaScript at build time.

The framework churn became so intense that "JavaScript fatigue" entered the developer vocabulary around 2015-2016. New frameworks, build tools, and paradigms appeared monthly. The joke "by the time you finish reading this sentence, three new JavaScript frameworks have been released" became a standard conference one-liner. The fatigue was real, but it was also a sign of health: JavaScript's ecosystem was evolving faster than any other language's because the stakes (controlling the browser platform) were higher.

TypeScript and the Type Renaissance

JavaScript's lack of a static type system was, from the beginning, both a feature and a bug. For small scripts, dynamic typing was liberating. For large applications with thousands of files and dozens of developers, it was a source of subtle, hard-to-find errors. The absence of types also made tooling (autocompletion, refactoring, navigation) less reliable.

Several attempts to add types to JavaScript had failed or remained niche: Google's Closure Compiler annotations, Facebook's Flow, and various academic projects. TypeScript, released by Microsoft in 2012 under the leadership of Anders Hejlsberg (the designer of Turbo Pascal, Delphi, and C#), succeeded where others had not. Its key insight was gradual adoption: TypeScript was a strict superset of JavaScript, meaning any valid JavaScript was valid TypeScript. Teams could adopt it incrementally, adding types to existing code one file at a time.

By 2024, TypeScript had become the default for new professional JavaScript projects. The State of JavaScript surveys showed TypeScript satisfaction rates above 90%. Major frameworks (Angular, Next.js, Remix) were written in TypeScript. The npm registry showed TypeScript adoption growing year over year. The language that Brendan Eich built in ten days without types had acquired a type system maintained by the designer of C#. The irony was not lost on anyone.

Node.js and the Great Escape

In 2009, Ryan Dahl created Node.js by extracting V8, Google Chrome's JavaScript engine, and wrapping it with an event-driven I/O layer. JavaScript could now run on servers. This was philosophically important: a frontend developer could write the entire stack in one language. The "JavaScript everywhere" dream was born.

npm, the Node Package Manager, launched in 2010 and grew into the largest software registry in the world. The JavaScript ecosystem exploded with frameworks, libraries, and tools. Express, Angular, React, Vue, Webpack, Babel, TypeScript. The rate of innovation was staggering (and sometimes exhausting). "JavaScript fatigue" became a common complaint.

The Modern Language

JavaScript today bears little resemblance to what Eich built in 1995. ES6 (2015) was a transformative update, adding classes, arrow functions, template literals, destructuring, promises, modules, and more. Subsequent annual releases have continued adding features. TypeScript, Microsoft's typed superset of JavaScript, has become the default for large projects, addressing one of JavaScript's oldest criticisms.

JavaScript now runs on servers (Node.js, Deno, Bun), mobile devices (React Native), desktops (Electron), embedded systems, and even spacecraft. It powers everything from simple form validation to complex real-time applications. Frameworks like Next.js and Nuxt blur the boundary between server and client rendering.

The Runtime Explosion

JavaScript's colonization of non-browser environments continued beyond Node.js. Deno, created by Ryan Dahl in 2018 (the same person who created Node.js), was an explicit attempt to fix Node's design mistakes: it had built-in TypeScript support, a security-first permissions model, and native ES module support. Bun, created by Jarred Sumner in 2022, prioritized raw performance, implementing its runtime in Zig and claiming speeds several times faster than Node.js for common operations.

On the desktop, Electron (2013) wrapped Chromium and Node.js into a framework for building cross-platform desktop applications. VS Code, Slack, Discord, Figma, Notion, and dozens of other popular applications are Electron apps. The approach was criticized for memory consumption (each Electron app ships its own copy of Chromium), but it allowed web developers to build desktop apps without learning new languages or frameworks. Tauri, a more recent alternative, uses the system's native web view instead of bundling Chromium, reducing memory and binary size significantly.

React Native (2015) and Expo brought JavaScript to mobile development. While native mobile development (Swift for iOS, Kotlin for Android) remained preferred for performance-critical applications, React Native allowed teams to share code between web and mobile platforms, dramatically reducing development costs for startups and small teams.

JavaScript even reached embedded systems and IoT devices through projects like Espruino and Johnny-Five. SpaceX reportedly uses JavaScript (via Chromium) in the crew display interfaces of the Dragon capsule. The language designed for form validation in 1995 is now literally in space.

The Performance Story

Early JavaScript was slow. Netscape's original interpreter executed code line by line, with no optimization. Internet Explorer's JScript engine was no better. For years, JavaScript performance was a legitimate criticism. Complex calculations that took milliseconds in C or Java took seconds in JavaScript.

Google changed this calculus with V8 (2008), the JavaScript engine built for Chrome. V8 introduced just-in-time (JIT) compilation to JavaScript, compiling frequently executed code to native machine code at runtime. The performance improvement was dramatic: benchmarks showed V8 running JavaScript 10-100x faster than previous interpreters.

The browser vendors entered a performance arms race. Mozilla responded with SpiderMonkey's TraceMonkey (trace-based JIT), then JaegerMonkey, then IonMonkey. Apple's JavaScriptCore introduced the FTL (Fourth Tier LLVM) JIT compiler. Each improvement made JavaScript faster, which enabled more ambitious applications, which created demand for even more performance.

Modern JavaScript engines are engineering marvels. They perform speculative optimization (assuming types based on past execution and generating optimized code paths), inline caching (remembering how property lookups resolved previously), and garbage collection with concurrent marking (reclaiming memory without pausing the application). The gap between JavaScript and natively compiled languages, while still real, has narrowed to single-digit multiples for many workloads.

WebAssembly (Wasm), introduced in 2017, added another dimension. Wasm allows code written in C, C++, Rust, or other languages to run in the browser at near-native speed. Rather than replacing JavaScript, Wasm complements it: JavaScript handles the UI and business logic, while Wasm handles computationally intensive tasks like image processing, cryptography, and physics simulation. The browser has become a genuine application platform, and JavaScript is its scripting language and integration layer.

The Standardization Journey

JavaScript's survival and evolution owe much to its standardization through Ecma International. When Netscape submitted JavaScript to Ecma in 1996, the resulting ECMAScript specification became the common ground that prevented the language from fragmenting during the browser wars. But the standardization process was not always smooth.

ECMAScript 3 (1999) was the last uncontroversial update. The proposed ECMAScript 4, an ambitious overhaul that would have added classes, modules, optional typing, and many other features, was blocked in 2008 by Microsoft and Yahoo, who argued the changes were too disruptive. The committee instead produced ECMAScript 5 (2009), a modest update that added strict mode, JSON support, and array methods like forEach, map, and filter.

The real transformation came with ECMAScript 2015 (ES6), the largest single update in the language's history. ES6 added classes, arrow functions, template literals, destructuring, default parameters, rest/spread operators, Promises, iterators, generators, the let and const keywords, Map and Set data structures, Symbols, and a native module system. The update was so large that it took years for browsers to fully implement it, and tools like Babel (a "transpiler" that converted ES6 code to ES5) became essential parts of the development workflow.

Since ES6, the TC39 committee has adopted an annual release cycle, shipping smaller, incremental updates each year. ES2016 added exponentiation and Array.includes. ES2017 added async/await. ES2020 added optional chaining and nullish coalescing. Each update addressed real pain points identified by the community, and the annual cadence prevented the kind of multi-year deadlock that had stalled ES4.

The Package Ecosystem

npm (Node Package Manager), launched by Isaac Schlueter in 2010, grew into the largest software registry in the world. By 2024, it hosted over 2 million packages and served billions of downloads per week. The sheer size of the npm ecosystem became both JavaScript's greatest strength and a source of recurring controversy.

The "left-pad incident" of March 2016 exposed the fragility of the ecosystem. When developer Azer Koculu unpublished his packages from npm after a dispute with a corporation over the name "kik," one of the removed packages was "left-pad," an 11-line function that padded strings with spaces. Thousands of projects depended on left-pad, including React, Babel, and countless others. Their builds broke instantly. The incident raised uncomfortable questions: should an 11-line function be a package? Should one developer's personal dispute be able to break the internet?

The incident was a symptom of JavaScript's "micropackage" culture, where even trivial functions were published as npm packages rather than implemented locally. The culture emerged from a combination of factors: npm made publishing easy, Node.js's module system encouraged small, focused packages, and the community valued code reuse above all else. The result was a dependency graph of staggering complexity. A typical Node.js project might depend on thousands of packages, most of which the developer had never heard of.

Security incidents compounded the concerns. Event-stream, a popular npm package downloaded 2 million times per week, was compromised in November 2018 when a new maintainer injected code that stole Bitcoin wallet credentials. The ua-parser-js incident of October 2021 saw a popular package hijacked to distribute malware. Each incident strengthened the argument for dependency auditing and supply chain security, but the fundamental tension between code reuse and supply chain risk remained unresolved.

Yarn (2016, by Facebook) and pnpm (2017) emerged as alternatives to npm's CLI, offering faster installs, deterministic lockfiles, and better disk usage. But they all drew from the same npm registry. The ecosystem was a single point of success and a single point of failure.

JavaScript's Cultural Impact

JavaScript's cultural impact extends beyond technology. The language democratized programming in a way that few other technologies have. Because every computer with a web browser can run JavaScript, the barrier to entry for learning to program dropped to zero. No compiler to install, no IDE to configure, no dependencies to manage. Open a browser, press F12, and you can write JavaScript.

This accessibility created a generation of self-taught programmers. Codecademy, freeCodeCamp, and The Odin Project taught millions of people to code using JavaScript as the starting language. Bootcamps like General Assembly, Flatiron School, and Hack Reactor built their curricula around JavaScript. The "learn to code" movement of the 2010s was, in large part, a JavaScript movement.

The language's omnipresence also shaped software architecture. The "full-stack JavaScript" concept (Node.js on the server, React on the client, MongoDB for the database) became the default stack for startups. The MEAN stack (MongoDB, Express, Angular, Node) and later the MERN stack (replacing Angular with React) were taught in bootcamps and used in production at thousands of companies. The appeal was obvious: one language for everything meant faster development, easier hiring, and simpler mental models.

Critics argued that "JavaScript everywhere" was a case of the tail wagging the dog. Using JavaScript on the server, where Python, Go, or Java might be better suited, just because you already knew JavaScript, was not engineering. It was path dependence. The criticism was valid, but it did not slow adoption. Convenience beats optimality in most business contexts, and JavaScript was maximally convenient.

Key Takeaways