Skip to main content

Menu

System onlineAI Tutorials / 2026

AI Tutorials
Knowledge search

Recent · Popular · Tutorials

  • dart3 tutorials
  • java1 tutorial
  • Javascript3 tutorials
  • Node.js Introduction2 tutorials
  • dartdart · General · In depth
  • JavascriptJavascript · Advanced · In depth
  • JavascriptJavascript · Advanced · Mid
  • JavascriptJavascript · Advanced · Short

Find a tutorial

Tell the assistant what you want to learn. It suggests published chapters.

For example: “I want to learn Rust ownership from the start.” The conversation is kept only in this tab.

0 / 2,000 characters

Enter to send, Shift+Enter for a new line. Do not include personal information.

Chapter 11

Classes

Prerequisites: we assume you know functions, `this` binding, and the prototype chain — classes are syntax over that machinery, not a new object model.
Level: AdvancedLength: Mid2 min read

Read at another depth

Classes

Prerequisites: we assume you know functions, this binding, and the prototype chain — classes are syntax over that machinery, not a new object model.

Classes as prototype sugar

A class declaration creates a function whose prototype holds the methods. Instances share methods through the prototype chain; nothing is copied per instance. Fields declared in the class body, however, are per-instance properties created in the constructor.

Code example in javascript
class Greeter {
  static kind = "greeter";      // class-level, one copy
  #attempts = 0;                // private field, per instance
  constructor(name) { this.name = name; }
  greet() { return `Hello, ${this.name}`; }
  get attempts() { return this.#attempts; }
}
const g = new Greeter("Ada");
console.log(Object.getPrototypeOf(g) === Greeter.prototype); // true
console.log(typeof Greeter); // "function"

Gotchas that bite experienced developers

  • Class bodies are strict mode and non-hoisted. Unlike function declarations, classes are in the temporal dead zone until evaluated.
  • Methods are non-enumerable on prototype, but assignment (this.x = ...) is enumerable. Object.keys on instances misses prototype methods.
  • new is mandatory. Calling a class without new throws a TypeError; a normal constructor function would not.
  • Private fields (#x) are brand-checked, not just name-hiding: passing an object that lacks the field to a method expecting it throws even if it has a same-named public property.

Subclassing and extends

extends wires Child.prototype's prototype to Parent.prototype and makes super available. You must call super() before touching this in a derived constructor. static methods inherit too — through a second link (Object.getPrototypeOf(Child) === Parent).

Code example in javascript
class Timed extends Greeter {
  constructor(name, at) {
    super(name);
    this.at = at; // ReferenceError if before super()
  }
}

Trade-off: deep inheritance is usually the wrong tool in JavaScript. Composition with factories or mixins avoids the fragile-base-class problem and the awkwardness of super across sibling hierarchies.

Map, Set, and Built-in Collections

Plain objects coerce keys to strings and collide with prototype properties. Map keeps insertion order, accepts any key type, and offers O(1) size, iteration, and deletion.

FeatureObjectMap
Key typesstrings, symbolsany value, incl. objects
Key equalitystring identitySameValueZero (`NaN` works)
Sizemanual`map.size`
Iteration ordermostly insertion (integer keys first)guaranteed insertion

Set stores unique values with the same equality rule — ideal for deduplication ([...new Set(xs)]) and membership tests.

WeakMap and WeakRef

WeakMap holds keys weakly: a key object unreachable elsewhere can be garbage-collected, so it's the right structure for attaching metadata to objects you don't own, without leaking memory.

Code example in javascript
const meta = new WeakMap();
const el = { tag: "div" };
meta.set(el, { mounted: true });
// when el becomes unreachable, its entry is collectable

Selecting a structure

  • Keyed lookup with heterogeneous keys → Map.
  • Uniqueness / membership → Set.
  • Tags or caches keyed by object identity → WeakMap.
Code example in javascript
const events = new Map(); // node -> Set of handlers
function on(node, fn) {
  if (!events.has(node)) events.set(node, new Set());
  events.get(node).add(fn);
}
function off(node, fn) { events.get(node)?.delete(fn); }

Exercise

Why does new Set([1, "1"]) have size 2, and how does that differ from an object literal's keys?

Show answer

Set uses SameValueZero equality on the actual values, so the number 1 and the string "1" are distinct entries. An object literal would coerce "1" and [1]'s key forms to the same string key "1", colliding.

Exercise

A teammate reads a private-style property by convention (obj._cache) and complains #cache "does the same thing." What's the real difference?

Show answer

#cache is enforced by the engine with a brand check: the field exists only on instances created by that class, so foreign objects with a same-named public property still throw. Underscore-prefixed properties are plain public fields with no enforcement.

Spotted a mistake, or code that does not work?

Report an issue

Chapter: Classes

0 / 2,000 characters

Plain text, for example: the second code sample does not compile. Do not include personal information.

You can't do that