Creational pattern
Prototype
Instead of rebuilding an object from scratch every time, clone an already-configured instance — copy first, tweak second.
✗ The problem
Rebuilding costly, configured objects
Constructing an Enemy means loading a sprite, applying stats, wiring behavior —
every single time. Worse: sometimes you only hold an instance at runtime and don't even know
its concrete class to call new on.
class Enemy {
constructor(kind) {
this.sprite = loadSprite(kind); // slow I/O
this.stats = rollStats(kind); // heavy calc
this.buffs = [];
}
}
// spawning 50 orcs = 50 full rebuilds, duplicated everywhere
for (let i = 0; i < 50; i++) enemies.push(new Enemy('orc'));
Re-running heavy construction and duplicating setup code at every call site —
and if you only have an
enemy reference, not the Enemy class, you're stuck.
✓ The pattern
Copy an existing instance via
clone() →
Copy an existing instance via clone()
The object itself knows how to duplicate itself. No class lookup, no re-running setup — just copy the already-built state.
class Enemy {
constructor(cfg) { this.cfg = cfg; }
clone() {
// shallow copy — new object, same nested refs
return new Enemy({ ...this.cfg });
}
}
const orcProto = new Enemy({ kind: 'orc', hp: 40 });
const orc2 = orcProto.clone(); // cheap, independent
Prototype instance
fully configured
Independent copy
own state
Shallow copy duplicates top-level fields only — nested objects are still shared.
Need real independence for nested data? Deep-copy with
structuredClone(obj) or a recursive
spread.
✓ See it live
Configure a prototype, then clone it
Pick a color + level for the prototype (dashed card), then hit Clone. Each clone is an independent copy — editing the prototype afterwards never touches clones already made.
Color:
Level:
1
Prototype
Lv 1
0 clones spawned
✓ Takeaway
Build by copying, not constructing
- Clone a template instead of rebuilding — great when construction is costly, or when
the config is only known at runtime (no class to call
newon). - Shallow vs deep: spread /
Object.assigncopy top-level fields only; usestructuredClone()or a recursive copy for nested state. - Watch out: objects holding references/handles (open sockets, DOM nodes, file handles) can't be blindly cloned — decide per-field what "copy" even means.
🎯 Principle applied: Prototype favors composition/DRY — reuse a configured template instead of duplicating construction — and decouples clients from concrete constructors (Dependency Inversion).
Back to all topics →