class Entity { describe() { return "base"; } }
const Timestamped = (B) => class extends B {
describe() { return "ts>" + super.describe(); }
};
const Auditable = (B) => class extends B {
describe() { return "audit>" + super.describe(); }
};
class Invoice extends Timestamped(Auditable(Entity)) {}
console.log(new Invoice().describe());
ts>audit>baseIt prints ts>audit>base. The chain is built from the inside out: Auditable(Entity) extends Entity, and Timestamped(...) extends that. So Invoice finds Timestamped's describe first. Its super call goes to Auditable, and then to Entity.
"audit>ts>base" is tempting if you read the mixins as if they were applied left to right. The outermost call is the closest parent, so it runs first.
Read more