liveBook · Manning

Pseudoclassical model

As explained in The Joy of JavaScript

A JavaScript object-creation style that emulates class-based inheritance using constructor functions and prototype links.

The pseudoclassical model creates JavaScript objects with constructor functions, new, and prototype links, imitating class-based inheritance. ECMAScript 2015 classes streamlined this approach, but remain syntactic sugar over constructor functions. section 2.2.2 section 2.3

A typical pseudoclassical hierarchy combines several moving parts:

  • Define a parent constructor that assigns instance data, such as sender and recipient. section 2.2.2
  • Place shared methods on the constructor's prototype so instances reuse the same function. section 2.2.2
  • Call the parent constructor with Transaction.call(this, ...) to initialize inherited instance properties. section 2.2.2
  • Link the child prototype with Object.create(Parent.prototype), preserving delegated lookup through the prototype chain. section 2.2.2
  • Guard against omitted new with new.target or the older this instanceof Constructor check. section 2.2.2

Transaction and HashTransaction

function Transaction(sender, recipient) { this.sender = sender; this.recipient = recipient; }\nTransaction.prototype.displayTransaction = function() {\n return `Transaction from ${this.sender} to ${this.recipient}`;\n};\n\nfunction HashTransaction(sender, recipient) {\n if (!new.target) return new HashTransaction(sender, recipient);\n Transaction.call(this, sender, recipient);\n}\nHashTransaction.prototype = Object.create(Transaction.prototype);\nHashTransaction.prototype.calculateHash = function() { /* ... */ };\n\nconst tx = new HashTransaction('luis@tjoj.com', 'luke@tjoj.com'); section 2.2.2

Listing 2.6 Configuring the prototype chain using the constructor functions pattern
function Transaction(sender, recipient) {  
    this.sender = sender;
    this.recipient = recipient;
}
Transaction.prototype.displayTransaction = function displayTransaction() {
    return `Transaction from ${this.sender} to ${this.recipient}`;
} 
 
function HashTransaction(sender, recipient) {
    if (!new.target) { 
        return new HashTransaction(sender, recipient);
    }
    Transaction.call(this, sender, recipient);      
}
 
HashTransaction.prototype.calculateHash = function calculateHash() { 
    const data = [this.sender, this.recipient].join(''); 
    let hash = 0, i = 0;
    while (i < data.length) {
      hash = ((hash << 5) - hash + data.charCodeAt(i++)) << 0;
    }
    return hash**2;
}
 
HashTransaction.prototype = Object.create(Transaction.prototype);    #1
HashTransaction.prototype.constructor = HashTransaction;             #2
 
const tx = new HashTransaction('luis@tjoj.com', 'luke@tjoj.com');
const tx2 = new HashTransaction('luis@tjoj.com', 'luke@tjoj.com');
Transaction.prototype.isPrototypeOf(tx); // true
tx.calculateHash === tx2.calculateHash;  // true
tx.displayTransaction === tx2.displayTransaction; // true
tx.__proto__.__proto__; 
// Transaction { displayTransaction: [Function: displayTransaction] }

Inspect the complete constructor-function pattern, including parent initialization, child methods, prototype linking, and constructor references. section 2.2.2

How The Joy of JavaScript covers it

How deep it goes
Explains constructor calls, shared prototype methods, parent initialization, prototype links, invocation guards, and prototype-related hazards.
Examples
Uses Transaction and HashTransaction examples to demonstrate shared methods, inherited initialization, hashing, and equivalent class syntax.
What you can do after
Build it from scratch with constructor functions, prototype methods, parent calls, and explicit prototype-chain configuration.
How it connects
Connects constructor functions, prototypes, prototype chains, class inheritance, module patterns, and prototype pollution.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Joy of JavaScript. The section links point to the parts of the book it draws on.