[{"data":1,"prerenderedAt":153},["ShallowReactive",2],{"qa-\u002Fjavascript\u002Fobjects\u002Fprototypal-inheritance":3},{"page":4,"siblings":137,"blog":150},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"related":129,"seo":130,"seoDescription":131,"stem":132,"subtopic":6,"topic":133,"topicSlug":134,"updated":135,"__hash__":136},"qa\u002Fjavascript\u002Fobjects\u002Fprototypal-inheritance.md","Prototypal Inheritance",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"hard","md","JavaScript","javascript",{},true,3,"\u002Fjavascript\u002Fobjects\u002Fprototypal-inheritance",[23,28,32,36,40,44,49,53,57,61,65,69,73,77,81,85,89,93,97,101,105,109,113,117,121,125],{"id":24,"difficulty":25,"q":26,"a":27},"what-is-prototypal-inheritance","medium","What is prototypal inheritance?","A model where objects inherit directly from **other objects** (their prototype),\nrather than from classes. A missing property is looked up on the prototype\nchain, so one object can reuse another's properties and methods.\n\n```js\nconst animal = { eats: true, walk() { return 'walking' } }\nconst rabbit = Object.create(animal)\nrabbit.jumps = true\nrabbit.walk()  \u002F\u002F 'walking' — inherited\nrabbit.eats    \u002F\u002F true — inherited\n```\n\nJavaScript's inheritance is fundamentally object-to-object **delegation**. Even\n`class` is sugar over this prototypal mechanism.\n",{"id":29,"difficulty":25,"q":30,"a":31},"object-create-inheritance","How do you implement inheritance with Object.create?","`Object.create(proto)` makes a new object whose prototype is `proto`, giving you\ndirect prototypal inheritance with no constructors.\n\n```js\nconst base = {\n  init(name) { this.name = name; return this },\n  describe() { return `I am ${this.name}` },\n}\nconst child = Object.create(base)\nchild.shout = function () { return this.describe().toUpperCase() }\n\nconst c = Object.create(child).init('Ada')\nc.shout()  \u002F\u002F 'I AM ADA'\n```\n\nEach level delegates to the one above. This is the most direct expression of\nprototypal inheritance — no `new`, no `prototype` juggling.\n",{"id":33,"difficulty":14,"q":34,"a":35},"constructor-inheritance","How do you set up inheritance between constructor functions?","Call the parent constructor for the instance fields, and link the prototypes so\nmethods are inherited.\n\n```js\nfunction Animal(name) { this.name = name }\nAnimal.prototype.eat = function () { return `${this.name} eats` }\n\nfunction Dog(name) {\n  Animal.call(this, name)               \u002F\u002F inherit instance properties\n}\nDog.prototype = Object.create(Animal.prototype) \u002F\u002F inherit methods\nDog.prototype.constructor = Dog                 \u002F\u002F restore constructor\nDog.prototype.bark = function () { return 'woof' }\n```\n\nThis is the pre-ES6 pattern: `Parent.call(this)` for fields,\n`Object.create(Parent.prototype)` for the method chain, and reset\n`constructor`. `class extends` does all this for you.\n",{"id":37,"difficulty":25,"q":38,"a":39},"class-vs-prototypal","What is the difference between classical and prototypal inheritance?","- **Classical** (Java\u002FC++): classes are blueprints; objects are **instances**\n  that copy structure from the class hierarchy.\n- **Prototypal** (JavaScript): objects **delegate** to live prototype objects;\n  there's no copying, and the link is dynamic.\n\n```js\n\u002F\u002F prototypal: changing the prototype affects existing objects live\nconst proto = { greet() { return 'hi' } }\nconst obj = Object.create(proto)\nproto.greet = () => 'hello'\nobj.greet()  \u002F\u002F 'hello' — live delegation, not a copy\n```\n\nJavaScript's `class` *looks* classical but is prototypal underneath. The key\ndifference is delegation (live links) vs copying (static blueprints).\n",{"id":41,"difficulty":14,"q":42,"a":43},"super-in-prototypal","How do you call a parent method from a child (without class)?","Reference the parent prototype's method and invoke it with the right `this` via\n`call`.\n\n```js\nDog.prototype.eat = function () {\n  const base = Animal.prototype.eat.call(this)  \u002F\u002F call parent, keep `this`\n  return base + ' noisily'\n}\n```\n\nWith `class`, `super.method()` does this cleanly. Without classes, you must\nexplicitly grab `Parent.prototype.method` and `call` it with the instance, or\nthe parent method would run with the wrong `this`.\n",{"id":45,"difficulty":46,"q":47,"a":48},"override-method","easy","How does method overriding work with prototypes?","Define a method with the same name lower in the chain (on the child); it shadows\nthe parent's version because lookup stops at the first match.\n\n```js\nconst animal = { speak() { return '...' } }\nconst dog = Object.create(animal)\ndog.speak = function () { return 'Woof' }  \u002F\u002F overrides\ndog.speak()                                 \u002F\u002F 'Woof'\nObject.getPrototypeOf(dog).speak()          \u002F\u002F '...' (parent still reachable)\n```\n\nThe override is just a closer own\u002Fprototype property. The parent method remains\naccessible via the prototype if you need to call it (the manual `super`).\n",{"id":50,"difficulty":25,"q":51,"a":52},"factory-functions","What are factory functions and how do they relate to inheritance?","A factory function returns a new object without `new` or classes — often using\nclosures for state and composition (rather than prototype chains) for behavior.\n\n```js\nfunction createUser(name) {\n  return {\n    name,\n    greet() { return `Hi, ${name}` },\n  }\n}\nconst u = createUser('Ada')\n```\n\nFactories favor **composition over inheritance**: instead of inheriting from a\nprototype, you assemble objects from pieces. Trade-off: methods aren't shared on\na prototype (each object gets its own), costing some memory for many instances.\n",{"id":54,"difficulty":25,"q":55,"a":56},"mixins","What are mixins?","A way to share behavior across unrelated objects\u002Fclasses by **copying methods**\nin, instead of inheriting — JavaScript's answer to the lack of multiple\ninheritance.\n\n```js\nconst serializable = { serialize() { return JSON.stringify(this) } }\nconst comparable = { equals(o) { return this.id === o.id } }\n\nclass Model {}\nObject.assign(Model.prototype, serializable, comparable)\n```\n\nMixins let a class gain capabilities from several sources. They're a flexible\nalternative to deep inheritance — compose the behaviors a type needs rather than\nforcing a single hierarchy.\n",{"id":58,"difficulty":14,"q":59,"a":60},"diamond-problem","Does JavaScript have the diamond problem?","Not in the classic multiple-inheritance sense, because each object has a\n**single** prototype chain — there's no ambiguity over which parent a method\ncomes from. But **mixins** can reintroduce conflicts when two mixins define the\nsame method.\n\n```js\nconst a = { run() { return 'a' } }\nconst b = { run() { return 'b' } }\nObject.assign(target, a, b)\ntarget.run()  \u002F\u002F 'b' — last one wins, silently\n```\n\nWith `Object.assign`, the last source wins on key collisions (no error). So\nsingle-prototype inheritance avoids diamonds, but you must manage mixin method\nclashes yourself.\n",{"id":62,"difficulty":25,"q":63,"a":64},"prototype-vs-instance-property","Should shared state go on the prototype?","No — only **methods** (and true constants) belong on the prototype. Mutable\nshared state on a prototype is accidentally shared by all instances.\n\n```js\nfunction Cart() {}\nCart.prototype.items = []        \u002F\u002F ALL carts share one array\nconst a = new Cart(), b = new Cart()\na.items.push('x')\nb.items                          \u002F\u002F ['x'] — leaked!\n\nfunction Cart2() { this.items = [] }  \u002F\u002F per-instance state in the constructor\n```\n\nPut per-instance data on `this` in the constructor; put shared behavior on the\nprototype. (This mirrors the Java \"mutable static field\" trap.)\n",{"id":66,"difficulty":14,"q":67,"a":68},"inherit-static","Are static-like properties inherited?","Constructor functions have their **own** prototype chain\n(`Child.__proto__ === Parent` when using `class extends`), so \"static\"\nproperties on the parent constructor are inherited by the child constructor.\n\n```js\nclass Parent { static create() { return new this() } }\nclass Child extends Parent {}\nChild.create()   \u002F\u002F works — static method inherited; `this` is Child\n```\n\n`extends` links both chains: instance methods via `Child.prototype ->\nParent.prototype`, and statics via `Child -> Parent`. With plain constructor\nfunctions you'd wire statics up manually.\n",{"id":70,"difficulty":14,"q":71,"a":72},"object-create-second-arg","What is the second argument to Object.create?","A **property descriptors** object — it lets you define own properties (with\nwritable\u002Fenumerable\u002Fconfigurable flags) at the same time as setting the\nprototype.\n\n```js\nconst obj = Object.create(proto, {\n  id: { value: 1, enumerable: true },\n  secret: { value: 42, enumerable: false },\n})\n```\n\nIt's the same descriptor format as `Object.defineProperties`. Rarely needed, but\nit's how you create an object with both a chosen prototype and precisely\nconfigured own properties in one call.\n",{"id":74,"difficulty":14,"q":75,"a":76},"parasitic-inheritance","What is parasitic \u002F functional inheritance?","An older pattern where a factory creates a base object, then **augments** it with\nextra properties\u002Fmethods before returning it — inheritance without prototypes.\n\n```js\nfunction createAnimal(name) {\n  const obj = { name }\n  obj.eat = () => `${name} eats`\n  return obj\n}\nfunction createDog(name) {\n  const dog = createAnimal(name)   \u002F\u002F \"inherit\" by starting from a base\n  dog.bark = () => 'woof'          \u002F\u002F augment\n  return dog\n}\n```\n\nIt uses composition\u002Fclosures instead of the prototype chain. Methods aren't\nshared (memory cost), but it's simple and avoids `this`\u002F`new` pitfalls.\n",{"id":78,"difficulty":25,"q":79,"a":80},"hasownproperty-inheritance","Why can iterating an inheriting object surprise you?","`for...in` walks inherited enumerable properties too, so an object that inherits\nfrom another can expose more keys than you expect.\n\n```js\nconst proto = { shared: 1 }\nconst obj = Object.create(proto)\nobj.own = 2\nfor (const k in obj) console.log(k)   \u002F\u002F 'own' AND 'shared'\n```\n\nGuard with `Object.hasOwn(obj, k)`, or iterate `Object.keys(obj)` (own only).\nThis is why adding enumerable properties to built-in prototypes is dangerous —\nit pollutes every `for...in`.\n",{"id":82,"difficulty":14,"q":83,"a":84},"super-property-vs-method","How does inheritance interact with getters and setters?","Inherited accessors run with the instance as `this`, so a child can override a\ngetter\u002Fsetter while the parent's still computes against the child's data.\n\n```js\nconst base = {\n  get label() { return `[${this.name}]` },\n}\nconst item = Object.create(base)\nitem.name = 'box'\nitem.label   \u002F\u002F '[box]' — inherited getter, `this` is item\n```\n\nOverriding an inherited setter and writing to the property creates an own data\nproperty unless the child also defines an accessor — a subtle source of bugs\nwhen mixing data and accessor properties across a chain.\n",{"id":86,"difficulty":25,"q":87,"a":88},"composition-over-inheritance-js","Why is composition often preferred over inheritance in JavaScript?","Deep inheritance chains are rigid: a change in a base ripples to all\ndescendants, and an object is locked into one hierarchy. **Composition** builds\nobjects from small, swappable behaviors, which is more flexible.\n\n```js\nconst withTimestamp = (o) => ({ ...o, createdAt: Date.now() })\nconst withId = (o) => ({ ...o, id: crypto.randomUUID() })\nconst record = withId(withTimestamp({ name: 'Ada' }))\n```\n\nCompose capabilities (functions, mixins, delegation) instead of inheriting them.\nThis avoids the fragile-base-class problem and the \"gorilla holding the banana\nand the entire jungle\" inheritance trap.\n",{"id":90,"difficulty":25,"q":91,"a":92},"instanceof-inheritance","How do you check an object's type through an inheritance chain?","`instanceof` returns true for any constructor whose `prototype` is in the chain,\nso it sees inherited types.\n\n```js\nclass Shape {}\nclass Circle extends Shape {}\nconst c = new Circle()\nc instanceof Circle   \u002F\u002F true\nc instanceof Shape    \u002F\u002F true (ancestor)\n```\n\nFor prototypal (non-class) inheritance, use\n`proto.isPrototypeOf(obj)` to ask \"is this object in obj's chain?\" — the\ndelegation-style equivalent of `instanceof`.\n",{"id":94,"difficulty":25,"q":95,"a":96},"isprototypeof","What does isPrototypeOf do?","`proto.isPrototypeOf(obj)` returns true if `proto` appears anywhere in `obj`'s\nprototype chain — the object-oriented complement to `instanceof` (which works\nwith constructors).\n\n```js\nconst animal = {}\nconst dog = Object.create(animal)\nanimal.isPrototypeOf(dog)            \u002F\u002F true\nObject.prototype.isPrototypeOf(dog)  \u002F\u002F true\n```\n\nIt's the natural type check for prototypal inheritance built with\n`Object.create`, where there's no constructor to use with `instanceof`.\n",{"id":98,"difficulty":25,"q":99,"a":100},"shared-method-this","How does this behave in an inherited method?","An inherited method is called on the instance, so `this` is the **instance**,\nnot the prototype where the method is defined.\n\n```js\nconst proto = { whoAmI() { return this.name } }\nconst a = Object.create(proto); a.name = 'A'\nconst b = Object.create(proto); b.name = 'B'\na.whoAmI()  \u002F\u002F 'A'\nb.whoAmI()  \u002F\u002F 'B' — same method, different `this`\n```\n\nThis is what makes shared prototype methods useful: one definition operates on\nwhichever instance invokes it. Lose the receiver (extract the method) and `this`\nbreaks, as always.\n",{"id":102,"difficulty":25,"q":103,"a":104},"multiple-levels","Can you have multiple levels of prototypal inheritance?","Yes — chains can be arbitrarily deep, each level delegating to the next.\n\n```js\nconst a = { x: 1 }\nconst b = Object.create(a); b.y = 2\nconst c = Object.create(b); c.z = 3\nc.x  \u002F\u002F 1 (from a, two levels up)\nc.y  \u002F\u002F 2 (from b)\nc.z  \u002F\u002F 3 (own)\n```\n\nLookup walks `c -> b -> a -> Object.prototype -> null`. Deep chains work but get\nharder to reason about and slightly slower to traverse; flatter structures (or\ncomposition) are usually clearer.\n",{"id":106,"difficulty":14,"q":107,"a":108},"new-target","What is new.target and how does it help with inheritance?","`new.target` is the constructor that was invoked with `new` (or `undefined` for\na normal call). It lets a base constructor know which subclass is being built and\nenforce `new`.\n\n```js\nfunction Base() {\n  if (!new.target) throw new Error('Use new')\n  console.log(new.target.name)   \u002F\u002F logs the actual subclass\n}\nclass Sub extends Base {}\nnew Sub()   \u002F\u002F logs 'Sub'\n```\n\nUseful for abstract base classes (throw if `new.target === Base`) and for\nfactory logic that depends on the concrete type being constructed.\n",{"id":110,"difficulty":25,"q":111,"a":112},"prototype-chain-json","Does JSON.stringify include inherited properties?","No — `JSON.stringify` serializes **own enumerable** properties only, ignoring\nanything inherited from the prototype.\n\n```js\nconst proto = { inherited: 1 }\nconst obj = Object.create(proto)\nobj.own = 2\nJSON.stringify(obj)   \u002F\u002F '{\"own\":2}' — inherited is omitted\n```\n\nSo data on a prototype won't be serialized. If you need inherited values in\nJSON, copy them onto the object first (`{ ...proto, ...obj }`) or implement\n`toJSON`.\n",{"id":114,"difficulty":25,"q":115,"a":116},"when-classes-vs-prototypes","Should you use classes or raw prototypes today?","For most code, **use `class`** — it's clearer, standard, and handles the\nprototype wiring (`extends`\u002F`super`\u002Fstatics) correctly. Reach for raw\nprototypes\u002F`Object.create` only for low-level work, OLOO-style delegation, or\nunderstanding internals.\n\n```js\n\u002F\u002F idiomatic modern inheritance\nclass Animal { constructor(n) { this.name = n } speak() {} }\nclass Dog extends Animal { speak() { return 'Woof' } }\n```\n\nClasses and prototypes are the same machinery; classes just give you a safer,\nmore readable interface. Knowing prototypes still matters for debugging and edge\ncases.\n",{"id":118,"difficulty":25,"q":119,"a":120},"augmenting-instances","What is the cost of adding methods to instances vs the prototype?","Methods added to each **instance** are duplicated per object (more memory);\nmethods on the **prototype** are shared (one copy).\n\n```js\n\u002F\u002F a new function per instance\nfunction User(name) {\n  this.name = name\n  this.greet = function () { return this.name }\n}\n\u002F\u002F shared once\nUser.prototype.greet = function () { return this.name }\n```\n\nFor a handful of objects it doesn't matter; for thousands, prototype methods\nsave significant memory. Factory functions trade this away for closure-based\nprivacy — a deliberate choice.\n",{"id":122,"difficulty":25,"q":123,"a":124},"delegation-events","How does delegation in prototypes relate to event delegation?","Both are \"delegation\" but different ideas. **Prototypal delegation** forwards\n*property lookups* up the prototype chain. **Event delegation** attaches one\nlistener to a parent that handles events from many children via bubbling.\n\n```js\n\u002F\u002F event delegation (unrelated to prototypes)\nlist.addEventListener('click', (e) => {\n  if (e.target.matches('li')) handle(e.target)\n})\n```\n\nThey share a name and a \"let something else handle it\" spirit, but operate in\ncompletely different parts of the language\u002FDOM — a common point of confusion.\n",{"id":126,"difficulty":14,"q":127,"a":128},"clone-with-prototype","How do you clone an object while preserving its prototype?","Spread\u002F`Object.assign` copy own properties but give the clone a **plain object\nprototype**, losing the original's prototype. Preserve it explicitly:\n\n```js\nconst clone = Object.assign(\n  Object.create(Object.getPrototypeOf(original)),\n  original,\n)\n\u002F\u002F or structuredClone — but it does NOT preserve custom prototypes either\n```\n\n`{ ...obj }` and `structuredClone` both drop the custom prototype (the clone\nbecomes a plain object). To keep behavior, create the clone with\n`Object.create(getPrototypeOf(original))` then copy the own properties.\n",null,{"description":11},"JavaScript prototypal inheritance interview questions — Object.create, delegation, constructor inheritance, classical vs prototypal, and sharing behavior between objects.","javascript\u002Fobjects\u002Fprototypal-inheritance","Objects & Prototypes","objects","2026-06-18","GvqUS3PImrZ3Q2MJBGdT3949HLkhsnt0F70ivtrPQog",[138,142,145,146],{"subtopic":139,"path":140,"order":141},"Objects & Properties","\u002Fjavascript\u002Fobjects\u002Fobjects-properties",1,{"subtopic":143,"path":144,"order":12},"Prototypes & the Prototype Chain","\u002Fjavascript\u002Fobjects\u002Fprototypes-chain",{"subtopic":6,"path":21,"order":20},{"subtopic":147,"path":148,"order":149},"The new Operator & Constructors","\u002Fjavascript\u002Fobjects\u002Fnew-constructors",4,{"path":151,"title":152},"\u002Fblog\u002Fjavascript-prototypal-inheritance-guide","Prototypal Inheritance in JavaScript — The Complete Practical Guide",1781808676192]