Suggest an editImprove this articleRefine the answer for “Classes in JavaScript”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**A class is syntactic sugar over a constructor function and prototypes: `class` describes an object type declaratively, but the inheritance model stays prototypal.** The class body defines a `constructor` that runs on `new` and methods that land on `prototype` and are therefore shared by every instance. On top of that come `extends` and `super()` for inheritance, `static` for members of the class itself, `#` private fields and `get` / `set` accessors. ```javascript class User { constructor(name) { this.name = name; } sayHi() { console.log(`Hi, my name is ${this.name}`); } } new User('Alex').sayHi(); // Hi, my name is Alex ``` **Key point:** a class is convenient syntax over prototypes, not a new inheritance model.Shown above the full answer for quick recall.Answer (EN)Image**A class in JavaScript is syntactic sugar over a constructor function and prototypes.** From the outside it is a declarative description of an object type, while under the hood everything works exactly as before: methods land on `prototype`, and `new` creates a new object and binds `this` to it. Such code simply looks and reads much better. ## Theory ### TL;DR - `class` is syntactic sugar over a constructor function and prototypes, not a new inheritance model. - `constructor()` runs on `new`, and methods from the class body land on `prototype`, so they are shared by every instance. - `extends` links the prototypes of two classes, and `super()` calls the parent constructor. - `static` makes a method or property a member of the class itself rather than of an instance. - `#` fields are private and reachable only inside the class body (ES2022), while `get` / `set` control how properties are read and written. - Classes are not hoisted the way functions are, and their methods are non-enumerable. ### Quick example ```javascript class User { constructor(name, age) { this.name = name; this.age = age; } sayHi() { console.log(`Hi, my name is ${this.name}`); } } const user1 = new User('Alex', 25); user1.sayHi(); // Hi, my name is Alex ``` - `class` declares a class. - `constructor()` is the special method invoked by `new User()`. - `this` is a reference to the object being created. - Class methods automatically end up on `prototype`. ### What it looks like under the hood This code: ```javascript class User { constructor(name) { this.name = name; } sayHi() { console.log(this.name); } } ``` is equivalent to the old ES5 code: ```javascript function User(name) { this.name = name; } User.prototype.sayHi = function() { console.log(this.name); }; ``` The difference is not in the model but in the behaviour details: a class body always runs in strict mode, class methods are non-enumerable, so `for...in` over an instance will not see them, and a class cannot be called without `new` at all. ### Parts of a class | Feature | Description | | --- | --- | | **constructor()** | The method that runs when an object is created (`new`) | | **class methods** | Added to `prototype` and available to every instance | | **extends** | Inheritance from another class | | **super()** | A call to the parent constructor | | **static** | Static methods and properties that belong to the class itself | | **private fields** (`#`) | Fields that are unreachable outside the class | | **getters and setters** | Let you control how properties are read and written | A class can be declared not only as a statement but also as an expression (class expression): ```javascript const User = class { sayHi() { console.log('Hi!'); } }; new User().sayHi(); // Hi! ``` Or it can be given a name that is visible only inside the definition itself: ```javascript const User = class MyUser { getClassName() { return MyUser.name; } }; ``` ### Inheritance: extends and super ```javascript class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a sound.`); } } class Dog extends Animal { constructor(name, breed) { super(name); // calls the parent constructor this.breed = breed; } speak() { console.log(`${this.name} barks!`); } } const rex = new Dog('Rex', 'shepherd'); rex.speak(); // Rex barks! ``` - `extends` links the prototypes of the classes. - `super()` calls the parent `constructor`, and in a derived class it must run before the first use of `this`. - Methods can be overridden, just like in classic OOP. ### static, private fields and accessors Static methods and properties belong to **the class itself**, not to its instances: ```javascript class MathUtil { static add(a, b) { return a + b; } } console.log(MathUtil.add(2, 3)); // 5 ``` Private fields and methods (`#`) were added in ES2022: ```javascript class Account { #balance = 0; // private field deposit(amount) { this.#balance += amount; } getBalance() { return this.#balance; } } const acc = new Account(); acc.deposit(100); console.log(acc.getBalance()); // 100 console.log(acc.#balance); // error: private property ``` `#` fields are reachable **only inside the class**. Getters and setters let you control how a property is read and changed: ```javascript class User { constructor(name) { this._name = name; } get name() { return this._name.toUpperCase(); } set name(value) { this._name = value.trim(); } } const user = new User(' tim '); console.log(user.name); // TIM user.name = ' Alex '; console.log(user.name); // ALEX ``` ### Class versus constructor function | Criterion | Constructor function | Class | | --- | --- | --- | | Syntax | Old, verbose | Modern, declarative | | `new` required | Yes | Yes | | Methods | Through `prototype` | Inside the class body | | `this` behaviour | Can be unpredictable | Clear and standard | | `extends` support | Manual | Built in | | Private fields | None | Yes (through `#`) | A short syntax recap: | Concept | What it does | | --- | --- | | `class` | Declares a class | | `constructor` | The method invoked by `new` | | `extends` | Inheritance | | `super()` | A call to the parent constructor | | `static` | Methods of the class, not of an instance | | `#field` | A private property | | `get` / `set` | Control over property access | ### Common mistakes 1. **Assuming classes are hoisted the way functions are.** A class declaration lands in the temporal dead zone, so touching it above the `class` line throws: ```javascript const user = new User(); // ReferenceError class User {} ``` 2. **Calling a class without `new`.** `User('Alex')` throws `TypeError: Class constructor User cannot be invoked without 'new'`, while an old constructor function in the same call would quietly pollute the global object. 3. **Touching `this` before calling `super()`.** In a derived class `this` does not exist until the parent constructor has run, so you get a `ReferenceError`. 4. **Expecting class methods in `for...in`.** They are non-enumerable, unlike properties assigned to a prototype by hand. 5. **Passing a method as a callback and losing `this`.** `setTimeout(user.sayHi, 0)` calls the method unbound; you need `user.sayHi.bind(user)`, an arrow wrapper, or a class field holding an arrow function. 6. **Confusing `#balance` with the `_balance` naming convention.** The underscore is only an agreement between developers, while a `#` field really is unreachable from outside: referencing it outside the class body is a syntax error.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.