Skip to content
  • Classes · JavaScript

Classes

LearnViaNotes @learnvianotes· 3 min read

class is clean syntax over prototypes — with real extras: public and #private fields, static members, static blocks, accessors, and strict mode by default.

Anatomy of a class

JavaScript
class BankAccount {
  static bankName = "JS Bank";        // static field (on the class)
  static #count = 0;                  // private static field
  owner;                              // public instance field
  #balance = 0;                       // private instance field

  constructor(owner, deposit = 0) {
    this.owner = owner;
    this.#balance = deposit;
    BankAccount.#count++;
  }
  deposit(amount) {                   // method on BankAccount.prototype
    if (amount <= 0) throw new RangeError("amount must be positive");
    this.#balance += amount;
    return this;                      // enables chaining
  }
  get balance() { return this.#balance; }      // accessor
  #audit() { return `audited ${this.owner}`; } // private method
  report() { return this.#audit(); }
  static count() { return BankAccount.#count; }
}

const acc = new BankAccount("Asha", 100);
acc.deposit(50).deposit(25);
console.log(acc.balance, acc.report(), acc);
console.log(BankAccount.bankName, BankAccount.count(), typeof BankAccount);
Output
175 audited Asha BankAccount { owner: 'Asha' }
JS Bank 1 function

Private really means private

JavaScript
class Secret {
  #code = 1234;
  static isSecret(obj) { return #code in obj; }   // brand check (ES2022)
}
const s = new Secret();
console.log(s.code, Object.keys(s), JSON.stringify(s));
console.log(Secret.isSecret(s), Secret.isSecret({ code: 1 }));
Output
undefined [] {}
true false

Accessing s.#code outside the class body is a SyntaxError — the program does not even parse. Before #, the convention was a leading underscore (this._code), which is only a hint.

Class fields with arrow functions

JavaScript
class Button {
  label = "Save";
  handleArrow = () => `clicked ${this.label}`;   // per-instance, this is bound
  handleMethod() { return `clicked ${this?.label}`; }
}
const b = new Button();
const { handleArrow, handleMethod } = b;          // detach both
console.log(handleArrow(), "|", handleMethod.call(undefined));
console.log(Object.hasOwn(b, "handleArrow"), Object.hasOwn(b, "handleMethod"));
Output
clicked Save | clicked undefined
true false

Static blocks and getters

JavaScript
class Config {
  static defaults;
  static {
    // runs once when the class is defined
    Config.defaults = Object.freeze({ retries: 3, timeout: 1000 });
  }
  static get retries() { return Config.defaults.retries; }
}
console.log(Config.retries, Config.defaults);
Output
3 { retries: 3, timeout: 1000 }

Classes are special functions

BehaviourDetail
Must be called with newBankAccount() → TypeError: Class constructor … cannot be invoked without 'new'
Hoisted into the TDZUsing a class before its declaration throws ReferenceError
Strict modeThe whole class body is strict
Methods are non-enumerableThey do not show up in for…in over instances
Fields run per instanceInitialised before the constructor body (after super() in subclasses)
JavaScript
class Foo {}
try {
  Foo();
} catch (e) {
  console.log(e.message);
}
Output
Class constructor Foo cannot be invoked without 'new'

Are JavaScript classes real classes?

How do you make a property private?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report