Inheritance configuration arranges objects and prototype links so property lookup and behavior move through an inheritance chain. JavaScript links to objects rather than copying members from a class template. section 2.1 section 2.3
Common configurations differ in how explicitly they build and maintain the chain:
- Object.create establishes a child object whose prototype is an existing object; inherited properties remain available through the link. section 2.1
- Constructor functions place shared behavior on a prototype, while instances connect to that prototype through construction. section 2.3
- Classes and extends provide declarative syntax for configuring prototype chains, aligning constructor references and inherited public fields. section 2.3
- Property descriptors add control over enumerability, writability, configurability, and other property behavior during object creation. section 2.1
Linked transaction objects
const transaction = { sender: 'luis@tjoj.com', recipient: 'luke@tjoj.com' }; const moneyTransaction = Object.create(transaction); moneyTransaction.funds = 0.0; moneyTransaction.addFunds = function (funds = 0) { this.funds += Number(funds); }; moneyTransaction.addFunds(10.0); moneyTransaction.sender; // 'luis@tjoj.com' Object.getPrototypeOf(moneyTransaction) === transaction; // true A missing property causes lookup to continue upward until Object.prototype; an unresolved value produces undefined, while an unresolved function call produces a TypeError. section 2.1 section 2.1.1
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 class-based Transaction and HashTransaction listing makes the relationship between declared classes, inherited fields, private members, and extends concrete. section 2.3
