Inheritance links a specialized object or construct to a parent so it can reuse and extend behavior and data. JavaScript links objects through prototypes rather than copying from class blueprints; class and extends provide a streamlined form of the same model. section 2.3
The constructor-function approach requires explicit prototype-chain setup, such as Object.create(Transaction.prototype), and can fail through incorrect constructor references or missing new calls. Node.js util.inherits reduces boilerplate, but class and extends are preferred over it. section 2.2.2
JavaScript inheritance has practical tradeoffs:
- Prototype properties are shared by child instances, so later changes can ripple dynamically across them and contribute to prototype pollution. section 2.3
- Classes simplify inheritance syntax while retaining prototype-based lookup; private fields and methods support stronger encapsulation. section 2.3
- The module pattern offers another way to hide fee calculations and expose controlled construction and behavior without exporting object literals. section 2.3
Transaction and HashTransaction
A Transaction stores sender, recipient, and funds and exposes displayTransaction. HashTransaction extends Transaction, inherits its public fields and behavior, and adds transaction-specific hashing or identifiers. section 2.3
Listing 2.8 Transaction and HashTransaction objects defined using classes
class Transaction {
sender = ''; #1
recipient = ''; #1
funds = 0.0;
#feePercent = 0.6; #2
constructor(sender, recipient, funds = 0.0) {
this.sender = sender;
this.recipient = recipient;
this.funds = Number(funds);
}
displayTransaction() {
return `Transaction from ${this.sender} to ${this.recipient}
for ${this.funds}`;
}
get netTotal() {
return Transaction.#precisionRound(this.funds * this.#feePercent, 2);
}
static #precisionRound(number, precision) { #2
const factor = Math.pow(10, precision);
return Math.round(number * factor) / factor;
}
}
class HashTransaction extends Transaction { #3
transactionId;
constructor(sender, recipient, funds = 0.0) {
super(sender, recipient, funds); #4
this.transactionId = this.calculateHash();
}
calculateHash() {
const data = [
this.sender,
this.recipient,
this.funds
].join('');
let hash = 0, i = 0;
while (i < data.length) {
hash = ((hash << 5) - hash + data.charCodeAt(i++)) << 0;
}
return hash**2;
}
displayTransaction() {
return `${this.transactionId}: ${super.displayTransaction()}`;
}
}
const tx = new HashTransaction('luis@tjoj.com', 'luke@tjoj.com', 10);
tx.displayTransaction();
// Prints:
// 64284210552842720: Transaction from luis@tjoj.com to luke@tjoj.com for 10
A complete class-based example combines public fields, a constructor, an inherited subclass, private fee state, a getter, and a static helper. section 2.3


















