Home › Learn › JavaScript › Async, errors, and classes

Classes

Lesson 39 of 40. Bundle data with the methods that work on it.

class Counter { ... } describes objects of a kind. The constructor runs on new Counter() and sets properties on this; methods are written without the function keyword and reach the object through this. get area() { ... } defines a getter, read like a property: rect.area. static methods belong to the class itself.

class Dog extends Animal inherits; super(name) in the constructor runs the parent's constructor, and a method with the same name overrides the parent's. toString() controls how the object appears in a template literal or String(obj). Class names are CapWords.

class Account {
  constructor(owner) {
    this.owner = owner;
    this.balance = 0;
  }
  deposit(amount) {
    this.balance += amount;
    return this.balance;
  }
}
const a = new Account("Ada");
a.deposit(50);
console.log(a.balance);   // 50

Your task

Write class Receipt constructed with a customer name, holding an empty lines array, with a method add(label, amount) that appends { label, amount } and returns the receipt itself, a getter total giving the sum of the amounts rounded to two decimals, and toString() returning Receipt for <customer>: <n> lines, total <total>. Then write class GiftReceipt extends Receipt whose toString() returns Gift receipt for <customer>: <n> lines, with no amounts.

Part of the final project. Receipt collects the labeled amounts of an order and totals them. It is saved in this browser and loaded into Project: checkout when you get there.

Hint 1

constructor(customer) { this.customer = customer; this.lines = []; } add(label, amount) { this.lines.push({ label, amount }); return this; }

Hint 2

get total() { return Math.round(this.lines.reduce((sum, l) => sum + l.amount, 0) * 100) / 100; } and in GiftReceipt only toString is overridden; the constructor is inherited.

Show the solution
class Receipt {
  constructor(customer) {
    this.customer = customer;
    this.lines = [];
  }
  add(label, amount) {
    this.lines.push({ label, amount });
    return this;
  }
  get total() {
    return Math.round(this.lines.reduce((sum, l) => sum + l.amount, 0) * 100) / 100;
  }
  toString() {
    return `Receipt for ${this.customer}: ${this.lines.length} lines, total ${this.total}`;
  }
}

class GiftReceipt extends Receipt {
  toString() {
    return `Gift receipt for ${this.customer}: ${this.lines.length} lines`;
  }
}

    Runs in an isolated web worker in this tab; nothing is sent anywhere.