Condensed explanations for each acceptance criterion. Code references point into the corresponding annotated file.
Every object has an internal [[Prototype]] link to another object (or
null). Property lookup checks the object itself first, then walks up the
chain until the property is found or the chain ends at null.
Function.prototypeis the object that becomes the[[Prototype]]of instances created withnew SomeFunction().obj.__proto__is the (legacy but still common) accessor for an object's actual[[Prototype]];Object.getPrototypeOf(obj)is the modern equivalent.class/extendsare syntax sugar over the same prototype-linking mechanism —extendssetsChild.prototype's[[Prototype]]toParent.prototype.- Methods defined on a prototype are shared by all instances (one copy in
memory); properties set with
this.x =inside a constructor are per-instance.
Reference: 01-prototypes.js
- Destructuring pulls values out of arrays/objects into variables, including with renaming, defaults, and nested patterns.
- Spread (
...) expands an iterable/object into individual elements/properties — used in array/object literals and function calls. - Rest (
...) is the inverse — collects remaining items into a single array, only valid as the last function parameter or in a destructuring pattern. - Optional chaining (
?.) short-circuits toundefinedinstead of throwing when accessing a property/method onnull/undefined. - Nullish coalescing (
??) provides a default only fornull/undefined— unlike||, it does not treat0,"", orfalseas missing.
Reference: 02-es6-plus.js
- An iterable has a
Symbol.iteratormethod returning an iterator. - An iterator is any object with
.next()returning{ value, done }. for...of, spread, and destructuring all work on anything iterable.- A generator function (
function*) is a shortcut for writing an iterator: each call returns a generator object, andyieldpauses execution, returning a value, until.next()is called again. yield*delegates iteration to another iterable/generator.- Generators are lazy — values are only produced when requested, which
is what makes infinite sequences (like
naturalNumbers()) practical.
Reference: 03-iterators-generators.js
- ES modules (
import/export) are static — resolved at parse time, which enables tree-shaking, and always run in strict mode. - CommonJS (
require/module.exports) is dynamic —require()is a regular function call, evaluated synchronously at runtime, which allows conditional requires but blocks tree-shaking. - ES modules support asynchronous, lazy loading via
import(); CommonJSrequire()is always synchronous and blocks until the module is fully evaluated. - Node.js supports both; the choice is signaled by file extension
(
.mjs/.cjs) or the"type"field inpackage.json.
Reference: 04-modules-notes.md, es-modules-example/, commonjs-example/
- Module pattern: an IIFE closure that exposes only the public API, keeping internal state private.
- Singleton: a class that hands back the same instance on every construction call, guaranteeing exactly one instance exists.
- Factory: a function that builds and returns different object shapes
based on input, without exposing constructor/
newdetails to the caller. - Observer: an object (
EventEmitter) that lets other code subscribe to named events and get notified when they fire — decouples the event source from its reactions.
Reference: 05-design-patterns.js