Technology  /  JavaScript

🟨 JavaScript 15 guides · updated 2026

Closures, the event loop, promises, and modern ES syntax — the language of the web explained the way it actually behaves at runtime.

How JavaScript Actually Runs: Engines, Runtimes, and the Language’s Real Story

JavaScript is the most-deployed programming language in history — it runs on effectively every phone, laptop, and server-adjacent surface on Earth — and it’s also the language most people learn backwards. They start with document.getElementById, absorb a pile of framework habits, and never form a model of what’s actually executing their code. Then the weird parts of JS (and there are weird parts) feel like random hazing instead of explainable history.

This guide is the missing first chapter: where JavaScript came from, what an engine and a runtime actually are, how your code gets executed, and why the language behaves the way it does. Everything else in this series builds on this foundation.


Ten Days in 1995: The History That Explains the Quirks

JavaScript was created by Brendan Eich at Netscape in ten days in May 1995. That’s not an exaggeration for effect — it’s the documented timeline, and it explains more about the language than any other single fact.

Netscape wanted a lightweight scripting language for web pages — something designers could sprinkle into HTML, forgiving of errors, requiring no compiler. Eich originally wanted to build something Scheme-like; management wanted it to “look like Java” for marketing reasons (Java was the hot new thing). The name “JavaScript” was pure marketing — Java and JavaScript are unrelated languages that share four letters and nothing else of consequence.

The ten-day birth left artifacts you still live with:

In 1997, the language was standardized as ECMAScript (Netscape submitted it to the Ecma standards body; “JavaScript” was trademark-encumbered). That’s why you see “ES6”, “ES2015”, “ES2023” — versions of the ECMAScript specification. The transformative release was ES6/ES2015, which added let/const, classes, modules, arrow functions, promises, and destructuring — effectively the modern language. Since then, a new spec lands every June, and the language you should learn (and this series teaches) is the post-2015 one.

The other historical constraint that shapes everything: “don’t break the web.” Every quirk shipped in 1995 must work forever, because billions of pages depend on old behavior. JavaScript evolves strictly by addition. That’s why old bad features (like var, or ==) still exist alongside their replacements (let/const, ===) — and why learning JS well is partly learning which half of the language to use.


Engine vs. Runtime: The Distinction That Unconfuses Everything

When people say “JavaScript runs in the browser,” they’re blurring two layers that are worth separating.

The engine executes the language itself — parsing your source, compiling it, running it, managing memory. The major engines:

The runtime wraps an engine and provides everything else — the APIs your code calls that aren’t part of the language:

┌─────────────── Browser runtime ───────────────┐ ┌───────────── Node.js runtime ────────────┐
│ V8 engine (the language itself) │ │ V8 engine (the same language) │
│ + DOM (document, elements, events) │ │ + file system (fs), network sockets │
│ + fetch, timers, localStorage, canvas... │ │ + process, streams, fetch, timers... │
│ + the event loop (from the browser) │ │ + the event loop (from libuv) │
└───────────────────────────────────────────────┘ └──────────────────────────────────────────┘

This is why document.querySelector doesn’t exist in Node, and why fs.readFile doesn’t exist in a browser — neither is JavaScript. They’re runtime APIs. The language — closures, promises, arrays, objects — is identical in both. Internalizing this split pays off constantly: when you read documentation, you’ll know whether you’re learning JavaScript (portable everywhere) or a runtime’s API (portable nowhere).

Notably, even things that feel core to JS — setTimeout, console.log, fetch — are runtime APIs, not language features. The ECMAScript spec doesn’t define any of them.


What Happens When Your Code Runs

JavaScript is often called an “interpreted language,” which was true in 1995 and is misleading now. Modern engines are sophisticated JIT (just-in-time) compilers, and the pipeline matters for understanding performance:

  1. Parse — source code becomes an AST (abstract syntax tree). Syntax errors surface here, before anything runs.
  2. Baseline execution — an interpreter (V8’s is called Ignition) starts executing bytecode immediately. Fast to start, modest speed.
  3. Optimization — the engine profiles as it runs. Functions that run hot get compiled to optimized machine code (V8’s TurboFan), with aggressive assumptions based on observed behavior: “this variable has always been a number; compile arithmetic accordingly.”
  4. Deoptimization — if an assumption breaks (that “always a number” variable suddenly gets a string), the engine throws away the optimized code and falls back. Correct behavior, big performance cliff.

You don’t need to think about this daily, but it explains real phenomena: why JS can be shockingly fast (near-native for hot numeric loops), why performance advice says keep object shapes consistent and don’t change a variable’s type mid-flight, and why microbenchmarks lie (they measure whichever tier happened to be active).

One more execution fact that shapes the whole language: JavaScript is single-threaded. One call stack, one statement executing at a time. There is no “spawn a thread” in the core language. Instead, JS handles concurrency through the event loop — an architecture where slow operations (network, timers, disk) are delegated to the runtime, and their callbacks run later, one at a time, when the stack is free. This design is why JS is so async-heavy — callbacks, promises, async/await — and it’s important enough to get its own deep dive in this series. For now, hold the one-sentence version: JavaScript never waits; it schedules.


Where JavaScript Runs Now

The 1995 pitch was “scripts for web pages.” The 2026 reality:

The strategic consequence: JavaScript is the highest-leverage single language for anyone working near the web, because one language covers client, server, and tooling. Its flaws are real, but “learn it once, use it everywhere” has proven to be an unbeatable proposition.

A note on TypeScript, because you’ll meet it immediately: TypeScript is JavaScript plus a static type layer, compiled down to plain JS before running. It has become the default for serious projects. Everything in this series is TypeScript-relevant — TS is JS at runtime — and learning JS deeply first makes TS’s type system make sense rather than feel like ritual.


Your First Real Look at the Language

You can follow this entire series with zero installation: every browser ships a console (F12 → Console tab), which is a full JS REPL. Or install Node and run node for the same thing in a terminal. Try this:

// values and variables — const by default, let when reassignment is needed
const language = "JavaScript";
let age = 2026 - 1995;
// template literals — modern string building
console.log(`${language} is ${age} years old`);
// functions are values you can pass around — the heart of JS style
const twice = (f, x) => f(f(x));
const inc = (n) => n + 1;
console.log(twice(inc, 40)); // 42
// objects are ad-hoc and flexible
const engine = { name: "V8", vendor: "Google", browsers: ["Chrome", "Edge"] };
console.log(engine.browsers.length); // 2
// and the famous coercion quirks are real — we'll tame them next chapter
console.log("5" + 1); // "51"
console.log("5" - 1); // 4

That fifth line — passing a function to a function — is the single most JavaScript thing in the snippet. Functions as first-class values shape everything: array methods, event handlers, promises, React components. If you come from Java, this is the mental shift; JS got lambdas-everywhere twenty years before Java 8 did.


A Map of the Weird (So It Doesn’t Ambush You)

An honest orientation to the rough edges, each covered properly later in the series:

QuirkOne-line previewDeep dive
== vs ===== coerces types before comparing; always use ===Types & coercion
var hoistingvar ignores block scope; use let/constVariables & scope
thisDepends on how a function is called, not where it’s writtenThe this keyword
ClosuresFunctions remember variables from where they were bornClosures
Async timingsetTimeout(fn, 0) doesn’t run “immediately”Event loop
0.1 + 0.2 !== 0.3Floating point, same as every languageTypes & coercion

Two reassurances. First: the modern language, written with current idioms (const, ===, arrow functions, modules, async/await), avoids most of the traps by construction — the quirks mostly live in the legacy half you’ll learn to recognize and not write. Second: every quirk has a mechanical explanation. JS is not random; it’s over-backward-compatible. The aim of this series is that nothing in the language feels like magic — just history plus rules.


Frequently Asked Questions

Should I learn JavaScript or TypeScript first? JavaScript — but briefly. Learn the core language (this series), then adopt TypeScript early in real projects. TS errors are incomprehensible without understanding the JS underneath; JS-without-types is unpleasant to maintain at scale. They’re one skill with two stages, not competitors.

Do I need to learn jQuery / older patterns? No for new work; recognition-level only for maintaining old code. Modern DOM APIs (querySelector, fetch, classList) absorbed jQuery’s good ideas years ago.

Which runtime should I practice in? Browser console for DOM-adjacent experiments, Node for everything else — the language is identical. When this series touches runtime-specific APIs (like fetch or the DOM), it says so explicitly.

Is JavaScript slow? For the single-threaded, IO-heavy work it typically does — no; V8 is an engineering marvel, and the event-loop model handles massive concurrency well. For CPU-parallel number crunching, it’s the wrong tool (that’s what workers and WebAssembly patch over). Right tool, right job.

How much of this can AI tools write for me now? A lot of the typing — and none of the judgment. Generated code with a subtle this bug, a swallowed promise rejection, or an accidental type coercion looks exactly like working code. The developers who thrive with AI assistance are the ones who can read a diff and spot what’s wrong — which is precisely the mental-model knowledge this series builds.


What’s Next

You now have the frame: a ten-day language standardized as ECMAScript, executed by JIT-compiling engines, embedded in runtimes that add the APIs, single-threaded with an event loop, evolving by addition, weird for explainable reasons.

Next: Variables and Scopelet, const, the var you’ll learn to recognize and avoid, hoisting, and the scoping rules that closures (the language’s crown jewel) are built on.