What Is JavaScript? ECMAScript, Engines and Where It Runs
JavaScript is a dynamically typed language with first-class functions, prototypes and an event loop. How ECMAScript editions work and where JavaScript runs.
- Course: JavaScript study plan
- Module: JavaScript and its runtime
- Kind: Lesson
- Reading time: 12 min
- Runtime: Node 16
What is JavaScript?
JavaScript is a dynamically typed programming language with first-class functions, prototype-based objects and a single-threaded event loop. Its specification is ECMAScript, published every year by the TC39 committee, and engines such as V8 implement it. It runs in every web browser, on servers through Node.js, Deno and Bun, and inside desktop, mobile and embedded applications.
Lesson
JavaScript was written in ten days in 1995 to make web pages move, and it now runs the browser, the server (Node), the phone (React Native), the desktop (Electron) and the build tools of every other language. It is the only language every web developer must know and, by most counts, the most used programming language in the world. Its shape — C-like syntax, first-class functions from Scheme, prototype-based objects from Self, dynamic types, one thread with an event loop — explains most of what will surprise you in this plan. This lesson is the map: what the language is, who defines it, where it runs, and what a JavaScript program is at its simplest.
Three names, one language
JavaScript is the language you write. ECMAScript is its specification, maintained by the TC39 committee and published yearly (ES2015 — also called ES6 — was the big modernisation; ES2016 onwards adds a few features each year). ECMA-262 is the document's number. The names "ES6", "ES2020", "ESNext" all refer to editions of the spec; engines implement the spec, and features move through four TC39 stages (proposal → draft → candidate → finished) before landing. Nothing about the language is owned by one company, which is why it evolves slowly and never breaks old code — a page written in 1998 still runs.
The design in five decisions
- Dynamic typing. Variables have no type; values do.
let x = 1; x = "one";is legal. The trade-off is flexibility against the runtime errors a compiler would have caught — which is why TypeScript exists and why this plan spends a whole module on values and coercion. - First-class functions and closures. Functions are values you can pass, return and store; an inner function remembers the variables around it. This is the heart of the language — callbacks, event handlers, promises, React components are all closures.
- Prototypes, not classes. Objects inherit directly from other objects through a prototype chain; the
classkeyword (2015) is a cleaner syntax over the same mechanism. - Single-threaded with an event loop. One thread runs your code; I/O happens elsewhere and calls back when done. No data races, no locks — and a program that blocks that one thread freezes everything.
- Forgiving semantics. Missing semicolons are inserted,
"5" * 2is10, undefined properties areundefinedrather than errors. Convenient for a ten-line script, treacherous in a ten-thousand-line application; the rules for staying safe are a recurring theme.
Where it runs
- Browsers — the original host. The language plus the DOM,
fetch,localStorageand the rest of the Web APIs. - Node.js (2009) — Chrome's V8 engine with file, network and process APIs instead of a DOM. Servers, CLIs, build tools. The runtime this plan judges on: Node 16.
- Deno and Bun — newer server runtimes with the same language and different standard libraries.
- Embedded — in databases, editors, game engines, and as the scripting layer of countless applications.
The language is the same everywhere; the host objects differ. console.log exists in all of them; document exists only in a browser; require("fs") only in Node.
Your first program
// hello.js
"use strict";
const name = "world";
console.log(`Hello, ${name}!`);
Run it with node hello.js. There is no class, no main, no compilation step you see — the file is the program, executed top to bottom. "use strict" at the top opts into strict mode, which turns several silent mistakes into errors (assigning to an undeclared variable, duplicate parameter names, writing to read-only properties); modules and classes are strict automatically, and every program in this plan should start with it.
Reading input, the judge's way
Exercises here read standard input and print to standard output, exactly like any other judged language:
const input = require("fs").readFileSync(0, "utf8"); // everything on stdin, as one string
const tokens = input.trim().split(/\s+/); // whitespace-separated tokens
const n = Number(tokens[0]);
console.log(n * 2);
Lesson 3 covers the alternatives; this one line is enough for now.
Versions you will hear about
| Edition | Year | Brought |
|---|---|---|
| ES5 | 2009 | strict mode, JSON, Array.prototype.map/filter/reduce |
| ES2015 (ES6) | 2015 | let/const, arrows, classes, template literals, destructuring, promises, modules, Map/Set |
| ES2017 | 2017 | async/await |
| ES2019–2020 | flat, optional catch binding, optional chaining ?., nullish ??, BigInt | |
| ES2021–2022 | replaceAll, logical assignment, class fields, at(), top-level await |
Node 16 supports everything through ES2022. Newer features (toSorted, structuredClone, the using declaration) are noted where they matter but not exercised.
Interview angle
- "Is JavaScript compiled or interpreted?" Both — engines parse to bytecode, interpret, and JIT-compile hot code to machine code (next lesson).
- "What is ECMAScript?" The specification JavaScript implements; editions are yearly.
- "Why is JavaScript single-threaded?" By design: one call stack, an event loop for I/O; simple concurrency model, no races.
- "What does
"use strict"do?" Turns silent errors into thrown errors and removes some unsafe behaviours; on by default in modules and classes. - "Node versus browser?" Same language and engine family; different host APIs (files and processes versus DOM and
fetch).
Key takeaways
- JavaScript = the language; ECMAScript = the yearly spec from TC39; engines implement it and never break old code.
- Dynamic types, first-class functions and closures, prototypes, one thread plus an event loop, forgiving coercion.
- Same language everywhere; host APIs differ. This plan runs on Node 16.
- A file is a program;
"use strict"at the top;readFileSync(0)reads all of stdin. - ES2015 is the modern baseline; know what each later edition added.
Common questions
What is the difference between JavaScript and ECMAScript?
ECMAScript is the specification and JavaScript is the language that implements it. The TC39 committee maintains ECMAScript and publishes a new edition every year, so names such as ES6 and ES2020 refer to editions of the spec that engines then implement.
What is ES6 in JavaScript?
ES6 is the 2015 edition of ECMAScript, also called ES2015, and the big modernisation of the language. It added let and const, arrow functions, classes, template literals, destructuring, promises, modules, Map and Set.
Is JavaScript compiled or interpreted?
Both. Engines parse the source to bytecode and start interpreting it at once, then JIT-compile the functions that run often into optimised machine code while the program runs. There is no separate compile step you run yourself.
What is the difference between JavaScript in the browser and Node.js?
The language is the same; the host objects differ. A browser adds the DOM, fetch and localStorage, while Node.js adds files, processes and modules through require("fs") and friends. console.log exists in both, document only in a browser.
Why is JavaScript single-threaded?
By design: one thread runs your code on one call stack, and I/O happens elsewhere and calls back through the event loop when it is done. That rules out data races and locks, but a program that blocks the thread freezes everything.
Exercises
Hello, strictly
Write a strict-mode program that reads an integer n and n names, prints Hello, <name>! for each using a template literal, then Greeted <n> person or Greeted <n> people. Use const for anything that does not change and let only for the loop counter.
Example: 2 then Ada Linus →
Hello, Ada!
Hello, Linus!
Greeted 2 peopleWhich edition?
Build a Map from feature name to the ECMAScript year that shipped it: let-const 2015, arrow-functions 2015, promises 2015, async-await 2017, flat 2019, optional-chaining 2020, nullish-coalescing 2020, bigint 2020, replaceAll 2021, class-fields 2022, at 2022, top-level-await 2022. Read n feature names and print <feature>: ES<year> or <feature>: unknown, then es6=<how many of the queried features are from 2015>.
Example: 3 then arrow-functions at jsx →
arrow-functions: ES2015
at: ES2022
jsx: unknown
es6=1