Modern JavaScript Quiz: ES2022, Bundlers and Tooling Test
Test modern JavaScript with 12 questions and three programs on ES2020 to ES2025 features, TC39 stages, polyfills, bundlers, tree shaking, testing and runtimes.
- Course: JavaScript study plan
- Module: Modern JavaScript and its tooling
- Kind: Checkpoint — cleared at 70%
- Reading time: 24 min
- Runtime: Node 16
Checkpoint — Modern JavaScript and its tooling is the checkpoint that closes the Modern JavaScript and its tooling module: a graded quiz and whole-program exercises, passed at 70%.
Instructions
This checkpoint covers the ES2020–2022 features and their pitfalls, the 2023+ additions and the TC39 stage process, how to detect features and write spec-faithful polyfills, the build pipeline (resolve, transpile, tree-shake, split, minify, source maps), the quality toolchain (ESLint flat config, Prettier, test runners, mocking, hooks and CI), and the runtime landscape with its web-standard core.
How it works. Twelve questions and three programs; 70% on the questions and every program accepted clears the module.
Before you start, make sure you can answer:
??versus||; howa?.b.cshort-circuits; why BigInt refuses to mix; which 2022 class features exist.- What
toSorted/with/Object.groupBy/Promise.withResolversdo; the TC39 stages and when a proposal is safe to adopt; why syntax cannot be polyfilled. - The build stages; what defeats tree-shaking; how code splitting and hashed chunks work; what source maps are for.
- Linter versus formatter; the shape of a good test; when to mock; what pre-commit and CI each run.
- Node/Deno/Bun/edge differences; the WinterCG common APIs; feature detection over sniffing.
The programs are a spec-faithful structuredClone polyfill (cycles, Dates, Maps, Sets, regexes, and a DataCloneError for functions), a miniature bundler that resolves an ESM graph, tree-shakes unused exports and emits one file, and a runtime-support planner that turns feature requirements and a target list into the polyfills and transpile target a build needs.
Common questions
Why can't syntax be polyfilled in JavaScript?
A runtime that lacks a piece of syntax, such as ?. or #private, fails to parse the whole file before any polyfill could run. Only a transpiler can rewrite syntax for an older target; built-in functions and methods can be feature-detected and filled in.
What defeats tree shaking?
Modules with side effects at import time, CommonJS require and other dynamic patterns, a single export default object holding many functions, and packages that omit "sideEffects": false. Named imports from ES modules keep a bundle prunable.
What should a pre-commit hook and CI each run?
A pre-commit hook runs fast checks on staged files — the formatter, eslint --fix and perhaps a type-check — so problems appear before the commit exists. CI runs the full gate on every push: npm ci, lint, tsc --noEmit, tests, the build and end-to-end tests.
Exercises
A structuredClone polyfill
Node 16 lacks structuredClone. Write structuredClonePolyfill(value) following the structured-clone algorithm: primitives returned as-is; functions and symbols throw an error named DataCloneError; a Map from originals to clones preserves cycles and shared references; Date, RegExp (source + flags), Map, Set, arrays and plain objects are cloned deeply; class instances become plain objects (prototype and methods lost). The starter builds an object with a cycle, a shared reference, a Date, a regex, a Map, a Set and a class instance, plus the JSON from line 1; print the checks: distinct=<> dataEqual=<> dataDistinct=<>, cycle=<clone.self === clone> sharedRefPreserved=<>, date=<> regex=<>, map=<> set=<>, pointIsPlain=<> x=<> distMethod=<typeof>, then function: DataCloneError and symbol: DataCloneError.
Example →
distinct=true dataEqual=true dataDistinct=true
cycle=true sharedRefPreserved=true
date=true regex=true
map=true set=true
pointIsPlain=true x=3 distMethod=undefined
function: DataCloneError
symbol: DataCloneErrorA miniature bundler
Line 1 is entry: <file>; the rest are modules as blocks starting // file: <name>, containing one-line statements: import { a, b } from "./x.js";, export const|let|function|class <name> …, and ordinary lines. Build the dependency graph from the entry (post-order so dependencies come first; a circular import prints warning: circular import <from> -> <to> and is not followed), tree-shake exports that no module imports (the entry keeps all of its own), and emit the bundle: for each module // ---- <name> followed by its lines with the import statements removed and the export keyword stripped. End with // dropped: <module:export, …> | order: <a -> b -> c> | unused modules: <names or ->. Names are unique across modules.
Example (excerpt): an entry importing slugify and log, a utils module also exporting unused debounce/throttle, a logger with unused warn, and an unreferenced module →
// ---- logger.js
const log = (m) => console.log(m);
// ---- utils.js
const slugify = (s) => s.toLowerCase().replace(/\s+/g, "-");
// ---- main.js
const title = slugify("Hello World");
log(title);
// dropped: logger.js:warn, utils.js:debounce, utils.js:throttle | order: logger.js -> utils.js -> main.js | unused modules: unused.jsA runtime-support planner
Line 1 lists targets as runtime version pairs (node 16.17 chrome 100 safari 15.4); the following lines are features. Using the starter's table of minimum versions and kinds, decide per feature: supported everywhere, polyfill (missing in <targets>) for built-ins, or transpile (missing in <targets>) for syntax; unknown names print unknown feature. Compare versions as dotted tuples — 16.17 is newer than 16.6, so never compare as floats. Finish with transpile target: ES<year> (the lowest level any target supports: Node 18+/Chrome 94+/Safari 15.4+ → 2022; Node 16/Chrome 85/Safari 14.1 → 2021; Node 14/Chrome 80/Safari 13.1 → 2020; else 2019), polyfills: <list or none>, syntax to transpile: <list or none>.
Example: node 16.17 chrome 100 safari 15.4 with optional-chaining, at, structuredClone, toSorted, using, fetch, flying-cars →
optional-chaining: supported everywhere
at: supported everywhere
structuredClone: polyfill (missing in node 16.17)
toSorted: polyfill (missing in node 16.17, chrome 100, safari 15.4)
using: transpile (missing in node 16.17, chrome 100, safari 15.4)
fetch: polyfill (missing in node 16.17)
flying-cars: unknown feature
transpile target: ES2021
polyfills: structuredClone, toSorted, fetch
syntax to transpile: usingIn this module: Modern JavaScript and its tooling
- ES2020–ES2022 — the features that changed everyday code
- ES2023 onward, and how features get into the language
- Bundlers, transpilers and the build — what happens to your code before it runs
- Linting, formatting and testing — the quality toolchain
- Runtimes and the ecosystem — Node, Deno, Bun, browsers, edge, and the web-standard core
- Checkpoint — Modern JavaScript and its tooling (this lesson)
← Runtimes and the ecosystem — Node, Deno, Bun, browsers, edge, and the web-standard core · How V8 runs your code — parsing, tiers, hidden classes and inline caches →