Class Syntax (сахар над прототипами)
В одной фразе: class — синтаксический сахар, который помещает методы на prototype (non-enumerable), создаёт TDZ вместо hoisting и принудительно требует new. На собесе важно объяснить чем именно class отличается от function constructor.
// class vs function constructor — ключевые отличияclass Animal { constructor(name) { this.name = name; } speak() { return `${this.name} makes a sound`; }}
// Эквивалент вручную:function AnimalFn(name) { this.name = name; }AnimalFn.prototype.speak = function () { return `${this.name} makes a sound`;};
// Отличия:// 1. Animal нельзя вызвать без new (TypeError)// 2. speak из class — non-enumerable (не виден в for...in)// 3. class в TDZ (не hoisted полностью)// 4. Тело class всегда в strict mode// Геттеры, сеттеры, computed methods, Symbol.toPrimitiveclass Temperature { #celsius; // private field
constructor(c) { this.#celsius = c; }
get fahrenheit() { return this.#celsius * 9/5 + 32; } set fahrenheit(f) { this.#celsius = (f - 32) * 5/9; }
[Symbol.toPrimitive](hint) { if (hint === 'number') return this.#celsius; return `${this.#celsius}°C`; }}const t = new Temperature(100);t.fahrenheit; // 212t.fahrenheit = 32; // setter: celsius = 0+t; // 0 (Symbol.toPrimitive)// Методы на prototype — одна копия; arrow class field — на каждом экземпляреclass Foo { method() {} // Foo.prototype.method — одна функция arrowField = () => {} // собственное свойство каждого экземпляра}
const f1 = new Foo();const f2 = new Foo();
f1.method === f2.method; // true — одна ссылкаf1.arrowField === f2.arrowField; // false — разные функции
Object.hasOwn(f1, 'method'); // false — на prototypeObject.hasOwn(f1, 'arrowField'); // true — instance propertyИтог: Классы делают код читаемым, но не скрывают прототипную природу JS. Под капотом — те же prototype, [[Prototype]], функции-конструкторы.