Skip to content
Topic 15 of 16
Theory

Classes

Why it matters

Say there are a hundred enemies in a game. Each has a name, health, attack and the same actions: "hit", "take damage". Writing a hundred objects by hand takes forever. A class is a blueprint: you can create as many objects of one kind from it as you like. Such an object is called an instance of the class.

Many libraries are built on classes, and the built-in Map, Set, Date, Error are classes too.

Declaring a class

class User {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greet() {
    return `Hi, I'm ${this.name}`;
  }
}

const anna = new User("Anna", 15);
const timur = new User("Timur", 17);
console.log(anna.greet());
console.log(timur.age);

Output:

Hi, I'm Anna
17
  • class User { … } — a class declaration. Class names start with a capital letter.
  • constructor — a special method called when an object is created. Properties are set in it.
  • this — the object being created. this.name = name puts the value into its name property.
  • new User(…) — create an instance. Without new you get an error.
  • Methods (greet) are written inside the class without the word function and without commas between them.

Methods change state

class Counter {
  constructor() {
    this.value = 0;
  }
  increase(step = 1) {
    this.value += step;
    return this.value;
  }
}

const c = new Counter();
c.increase();
c.increase(5);
console.log(c.value);

Output:

6

Each instance keeps its own properties: two different Counters count independently.

Getters and setters

A getter is a method read like a property, without parentheses. A setter is a method that runs on assignment.

class Temperature {
  constructor(celsius) {
    this.celsius = celsius;
  }
  get fahrenheit() {
    return this.celsius * 9 / 5 + 32;
  }
  set fahrenheit(f) {
    this.celsius = (f - 32) * 5 / 9;
  }
}

const t = new Temperature(25);
console.log(t.fahrenheit);
t.fahrenheit = 212;
console.log(t.celsius);

Output:

77
100

A getter is handy for computed values and for "read-only": if there's no setter, you can't assign a value.

Private fields

A field whose name starts with # is visible only inside the class:

class Wallet {
  #money = 0;
  add(x) { this.#money += x; }
  get total() { return this.#money; }
}
const w = new Wallet();
w.add(50);
console.log(w.total);

Output:

50

Outside, w.#money is a syntax error. This protects data from accidental changes. The old-fashioned way is to mark "internal" fields with an underscore (this._money) — just a convention.

Inheritance: extends and super

A class can inherit from another: get all its properties and methods and add its own.

class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    return `${this.name} makes a sound`;
  }
  sleep() {
    return `${this.name} is sleeping`;
  }
}

class Cat extends Animal {
  speak() {
    return `${this.name} meows`;
  }
}

const kitty = new Cat("Kitty");
console.log(kitty.speak());   // its own method
console.log(kitty.sleep());   // inherited
console.log(kitty instanceof Cat, kitty instanceof Animal);

Output:

Kitty meows
Kitty is sleeping
true true

If the child class has its own constructor, it must first of all call super(...) — the parent's constructor:

class Student extends Animal {
  constructor(name, school) {
    super(name);          // the parent sets this.name
    this.school = school;
  }
  speak() {
    return super.speak() + " and answers the lesson";  // calling the parent's method
  }
}
console.log(new Student("Timur", "No. 5").speak());

Output:

Timur makes a sound and answers the lesson

Static methods

static is a method of the class itself, not of its instances: Math.max works in a similar way.

class MathUtil {
  static square(x) { return x * x; }
}
console.log(MathUtil.square(7));

Output:

49

How it works inside

Class methods aren't copied into each object — they live in one shared place, the prototype (User.prototype). When you call anna.greet(), JS first looks for greet in the object itself, doesn't find it, and goes to the prototype. With inheritance, prototypes form a chain: Cat.prototype → Animal.prototype → Object.prototype. The search goes along the chain until the method is found. That's why kitty.sleep() works even though Cat doesn't have it.

Common mistakes

  1. Without new. User("Anna") → TypeError: Class constructor User cannot be invoked without 'new'.
  2. Without this. name = name in the constructor doesn't save anything into the object. You need this.name = name.
  3. Forgot super(). Using this in a child constructor before super(...) is an error.
  4. Commas between methods. In a class, methods are written without commas (unlike in an object).
  5. A getter with parentheses. acc.balance() → "is not a function" error. A getter is read without parentheses: acc.balance.

Cheat sheet

What How
Class class Name { constructor(a) { this.a = a; } }
Instance const x = new Name(1);
Method go() { return this.a; }
Getter / setter get total() {…}, set total(v) {…}
Private field #secret = 0;
Inheritance class B extends A { … }
Parent super(…) in the constructor, super.method()
Static method static create() {…}
Check x instanceof Name

Rectangle

Easy+10 XP

Write a class Rectangle:

  • the constructor takes width and height and stores them in properties with the same names;
  • the method area() returns the area;
  • the method perimeter() returns the perimeter.
const r = new Rectangle(3, 4);
r.area()       → 12
r.perimeter()  → 14

Connect the connector to solve tasks

Task code runs on your own computer — faster and more reliable than in the browser. This needs the free CodeWithMe connector app. You only connect it once.

Looking for the connector on this computer…

  1. 1
    Download the connector for your system (Windows, macOS or Linux).Download the connectorOn the download page pick the file with your system in its name, e.g. windows-amd64.
  2. 2Run it and choose a folder for your solutions. It will install Python and Node.js there by itself when needed.
  3. 3
    Enter below the 6-digit code shown in the connector window (“Code for CodeWithMe”). If the browser asks about local network access — allow it.

The connector is open source (on GitHub), works only on your computer and runs code only after you enter the pairing code.