Card 05/ 08
Prototype in the Wild: JavaScript's Object.create
A whole language built on making objects from other objects.
JavaScript, and so TypeScript, is a prototype-based language: every object has a hidden link to another object, its prototype, and looks up any property it does not hold itself along that link. Object.create(p) makes a new, empty object whose prototype is p. This card shows how that resembles the pattern and where it differs from cloning.
interface Goblin {
health: number;
describe(): string;
}
const goblinPrototype: Goblin = {
health: 30,
describe() {
return `goblin with ${this.health} hp`;
},
};
const scout: Goblin = Object.create(goblinPrototype);
console.log(scout.describe());
console.log("own health property:", Object.prototype.hasOwnProperty.call(scout, "health"));
console.log("prototype is goblinPrototype:", Object.getPrototypeOf(scout) === goblinPrototype);
goblinPrototype.health = 40;
console.log("after the prototype changes:", scout.describe());
scout.health = 12;
console.log("after scout sets its own:", scout.describe(), "/ prototype:", goblinPrototype.describe());
const copied: Goblin = { ...goblinPrototype };
goblinPrototype.health = 50;
console.log("a spread copy keeps its value:", copied.describe());goblin with 30 hp
own health property: false
prototype is goblinPrototype: true
after the prototype changes: goblin with 40 hp
after scout sets its own: goblin with 12 hp / prototype: goblin with 40 hp
a spread copy keeps its value: goblin with 40 hpscout starts with no properties of its own, yet it describes itself with 30 hp, because health and describe are found on its prototype. Then the prototype's health changes to 40, and scout reports 40 too: nothing was copied, so the new object sees every later change. Only when scout sets health does it get a property of its own, which hides the prototype's from then on. The spread copy at the end behaves like the pattern's clone: it took the values at that moment and kept them.
What this shares with the Prototype pattern is the starting point: a new object begins from an existing, configured object instead of from a class. What differs is the relationship afterwards. A clone is independent of its original, while an object made by Object.create stays linked to it, so changing the prototype changes every object made from it. JavaScript's classes are built on this linking; the pattern's copying is something you write yourself, in a clone() method.
← → move through sections and cards