What JavaScript Is

Mental model: JavaScript is a single-threaded language that runs inside a host, and the host gives it superpowers.

Level: beginner · about 8 minutes

Run this in the console of any browser tab and in a terminal with node. The first two lines behave identically. The third does not.

console.log(typeof Math.max);    // → 'function'  every JavaScript, everywhere
console.log(typeof JSON.parse);  // → 'function'  same
console.log(typeof document);    // → 'object' in a browser page, 'undefined' in Node

Two of these come from the language. One comes from wherever the code happens to be running.

That split is the single most useful idea in this module. JavaScript the language gives you syntax, types, Math, JSON, Array, Promise. The host gives you everything that touches the outside world: the page, the filesystem, the network, timers. document is not part of JavaScript. Neither is fetch, alert or require.

ECMAScript
the written specification, maintained by TC39. One edition a year (ES2015, ES2024...)
JavaScript
what everyone calls the language. The name is a trademark, which is why the spec uses a different one
Engine
the program that reads and runs your code: V8, SpiderMonkey, JavaScriptCore
Host / runtime
the engine plus a set of APIs: a browser tab, Node, Deno, Bun, an edge worker

Engines and hosts

EngineBuilt byYou meet it in
V8GoogleChrome, Edge, Node, Deno, most edge platforms
SpiderMonkeyMozillaFirefox
JavaScriptCoreAppleSafari, Bun, iOS web views
        your code
            │
            ▼
     ┌─────────────┐        the language: syntax, Math, JSON,
     │   engine    │        Array, Promise, classes
     └─────────────┘
            │
   ┌────────┴─────────┐
   ▼                  ▼
┌────────┐        ┌────────┐
│browser │        │  Node  │   host APIs, not JavaScript:
│document│        │ fs     │   document, fetch, alert
│fetch   │        │process │   fs, process, require
└────────┘        └────────┘
  • Browser: the DOM, events, fetch, localStorage. Code is sandboxed away from your machine.
  • Node: files, sockets, child processes, process.argv. No DOM at all.
  • Deno and Bun: newer runtimes, browser-shaped APIs, TypeScript out of the box.
  • Edge workers: a trimmed browser-like host, no filesystem, short lifetimes.

One thread, and what that costs you

Your JavaScript runs on exactly one thread. One thing happens at a time. Anything scheduled for later waits until the current work finishes, no matter how impatient the delay looks.

console.log('start');
setTimeout(() => console.log('timer'), 0);

const until = Date.now() + 50;
while (Date.now() < until) {}   // the one thread is occupied

console.log('end');
// → start, end, timer

A 0 ms timer that waits about 50 ms, because the thread was busy.

console.log('a');
setTimeout(() => console.log('b'), 0);
Promise.resolve().then(() => console.log('c'));
console.log('d');

Everything synchronous runs first, so a then d. Then the queued work drains, and promise callbacks (microtasks) are served before timers, so c beats b. The single thread never interleaves any of it. You will build this ordering rule properly in the event loop module.

Try it yourself

Probe your host

const names = ['Math', 'JSON', 'Promise', 'document', 'localStorage', 'process'];

for (const name of names) {
  // typeof is the safe way to ask "does this name exist?" — it never throws for an
  // undeclared variable. But reading a property that DOES exist can still throw, and
  // here one does: this playground runs in a sandboxed frame on its own throwaway
  // origin, and a page with no origin is not allowed storage. So localStorage is
  // neither available nor missing. The host has it, and refuses to hand it over.
  let state;
  try {
    state = typeof globalThis[name] !== 'undefined' ? 'available' : 'missing';
  } catch (err) {
    state = 'blocked by the host (' + err.name + ')';
  }
  console.log(name.padEnd(14), state);
}

console.log('\nMath and JSON are the language itself. Everything else is the host,');
console.log('and a host can omit a feature, provide it, or refuse it.');

Add three more names to the list: fetch, Math, require. Which ones exist here, and which would only exist in Node? Note what localStorage does — a host can refuse as well as omit.

Exercises

Language, browser or Node?

Write whereItLives(name) which returns 'language' for Math, JSON, Promise, Array and Object; 'browser' for document, alert, localStorage and history; 'node' for process, require, __dirname and Buffer; and 'unknown' for anything else. Do not check the real environment, just classify the name.

Check yourself

What does this log in Node?
'object' 'undefined' — Math is part of the language so it exists in every host. document is a browser API, so in Node it is simply not there. typeof on a missing global gives 'undefined' rather than throwing, which is the one place typeof protects you.
Which of these is part of the JavaScript language itself?
JSON.parse — JSON is specified by ECMAScript, so it works in every engine. fetch and localStorage come from the browser (and were later copied into Node), and process is Node only. Hosts add APIs, the spec adds language.
JavaScript is single-threaded. What follows from that?
Your code never runs at the same time as other JavaScript in the same context — One thread means no two pieces of your JavaScript interleave, so you never need locks around a variable. Work can still happen elsewhere: the host can download, decode and time things off-thread, then queue the callback for your one thread to pick up. That is also why a 0 ms timer is a minimum delay, not a promise.

Common mistakes

  • Assuming document, fetch or require are part of JavaScript. They belong to a host, and change when you change host.
  • Reading setTimeout(fn, 0) as "run this now". It means "run this after the current work, at the earliest".
  • Confusing Java and JavaScript because of the name. The shared syllable is marketing from 1995.

Takeaways

  • The language gives you syntax and built-ins; the host gives you the outside world.
  • V8, SpiderMonkey and JavaScriptCore are engines. A browser tab, Node and Bun are hosts.
  • One thread runs your code, so long synchronous work blocks everything including rendering.
  • Engines compile hot code at runtime, which is why consistent types matter more than clever tricks.