[{"data":1,"prerenderedAt":146},["ShallowReactive",2],{"qa-\u002Fjavascript\u002Fclasses\u002Fclass-inheritance":3},{"page":4,"siblings":129,"blog":143},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":12,"path":20,"questions":21,"related":120,"seo":121,"seoDescription":122,"stem":123,"subtopic":124,"topic":125,"topicSlug":126,"updated":127,"__hash__":128},"qa\u002Fjavascript\u002Fclasses\u002Fclass-inheritance.md","Class Inheritance",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"hard","md","JavaScript","javascript",{},true,"\u002Fjavascript\u002Fclasses\u002Fclass-inheritance",[22,27,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116],{"id":23,"difficulty":24,"q":25,"a":26},"extends-keyword","easy","How does the extends keyword work?","`class Child extends Parent` makes `Child` inherit from `Parent`: instances get\n`Parent`'s methods via the prototype chain, and `Child` itself inherits\n`Parent`'s statics.\n\n```js\nclass Animal {\n  constructor(name) { this.name = name }\n  speak() { return `${this.name} makes a sound` }\n}\nclass Dog extends Animal {\n  speak() { return `${this.name} barks` }\n}\nnew Dog('Rex').speak()   \u002F\u002F 'Rex barks'\n```\n\n`extends` wires up two chains: `Dog.prototype -> Animal.prototype` (instance\nmethods) and `Dog -> Animal` (statics). It's the clean syntax for the manual\nprototype linking you'd otherwise write.\n",{"id":28,"difficulty":29,"q":30,"a":31},"super-constructor","medium","What does super() do in a constructor?","It calls the **parent constructor**, initializing the inherited part of the\ninstance. In a derived class you **must** call `super()` before using `this`.\n\n```js\nclass Dog extends Animal {\n  constructor(name, breed) {\n    super(name)        \u002F\u002F run Animal's constructor first\n    this.breed = breed\n  }\n}\n```\n\nThe parent constructor actually creates `this` for a derived class, which is why\n`super()` must come first. If a subclass has no constructor, a default one\ncalls `super(...args)` automatically.\n",{"id":33,"difficulty":29,"q":34,"a":35},"super-method","How do you call a parent method with super?","`super.method()` invokes the parent class's method with the current instance as\n`this` — for extending rather than fully replacing behavior.\n\n```js\nclass Dog extends Animal {\n  speak() {\n    return super.speak() + ' (woof)'   \u002F\u002F reuse parent, add to it\n  }\n}\n```\n\n`super` works in any method, getter, or static method — not just the\nconstructor. It resolves to the method on the *parent's* prototype, so overrides\ncan build on the inherited version.\n",{"id":37,"difficulty":14,"q":38,"a":39},"this-before-super","Why does using this before super() throw?","In a derived class, the instance object is created by the parent constructor via\n`super()`. Until `super()` runs, `this` is uninitialized, so accessing it throws\na `ReferenceError`.\n\n```js\nclass Dog extends Animal {\n  constructor(name) {\n    this.x = 1     \u002F\u002F ReferenceError: must call super first\n    super(name)\n  }\n}\n```\n\nThis is a real semantic difference from constructor functions (where `this`\nexists immediately). The rule ensures the parent has fully set up the object\nbefore the child modifies it.\n",{"id":41,"difficulty":24,"q":42,"a":43},"method-overriding","What is method overriding?","Defining a method in a subclass with the same name as the parent's — the\nsubclass version shadows the parent's for instances of the subclass.\n\n```js\nclass Shape { area() { return 0 } }\nclass Circle extends Shape {\n  constructor(r) { super(); this.r = r }\n  area() { return Math.PI * this.r ** 2 }   \u002F\u002F overrides Shape.area\n}\nnew Circle(2).area()   \u002F\u002F 12.56...\n```\n\nLookup finds the subclass method first. You can still reach the parent's version\nvia `super.area()`. Overriding is the basis of polymorphism.\n",{"id":45,"difficulty":29,"q":46,"a":47},"polymorphism-js","How does polymorphism work with classes?","Different subclasses override the same method, and calling that method on a\nbase-typed reference runs the actual object's version (dynamic dispatch).\n\n```js\nclass Shape { area() { return 0 } }\nclass Circle extends Shape { area() { return Math.PI * this.r ** 2 } }\nclass Square extends Shape { area() { return this.s ** 2 } }\n\nconst shapes = [new Circle(), new Square()]\nshapes.forEach(s => console.log(s.area()))  \u002F\u002F each runs its own area()\n```\n\nJavaScript dispatches methods at runtime by the object's prototype, so a\n`Shape[]` can hold mixed subclasses and each responds with its own behavior —\nclassic polymorphism.\n",{"id":49,"difficulty":29,"q":50,"a":51},"default-constructor","What is the default constructor in a subclass?","If a subclass omits a constructor, JavaScript inserts one that forwards all\narguments to the parent: `constructor(...args) { super(...args) }`.\n\n```js\nclass Animal { constructor(name) { this.name = name } }\nclass Dog extends Animal {}        \u002F\u002F implicit: constructor(...a){ super(...a) }\nnew Dog('Rex').name                \u002F\u002F 'Rex' — forwarded to Animal\n```\n\nSo you only need to write a subclass constructor when you add fields or change\nhow the parent is called. The default just chains to `super`.\n",{"id":53,"difficulty":14,"q":54,"a":55},"super-in-static","Can you use super in static methods?","Yes — in a static method, `super.method()` calls the **parent class's** static\nmethod, because static members are inherited along the constructor's own\nprototype chain.\n\n```js\nclass Base { static create() { return 'base' } }\nclass Derived extends Base {\n  static create() { return super.create() + '-derived' }\n}\nDerived.create()   \u002F\u002F 'base-derived'\n```\n\nThis works because `Derived.__proto__ === Base`, so `super` in a static context\nresolves to `Base`. Static inheritance is a real and sometimes-surprising part\nof `extends`.\n",{"id":57,"difficulty":14,"q":58,"a":59},"extends-builtins","How do you extend built-in classes like Array or Error?","Use `extends` directly — modern engines support subclassing built-ins, with\n`super()` initializing the built-in part.\n\n```js\nclass Stack extends Array {\n  peek() { return this[this.length - 1] }\n}\nconst s = new Stack()\ns.push(1, 2); s.peek()   \u002F\u002F 2 — inherits all Array methods\n\nclass AppError extends Error {\n  constructor(msg, code) { super(msg); this.name = 'AppError'; this.code = code }\n}\n```\n\nCaveat: extending `Error` historically needed `Object.setPrototypeOf(this,\nnew.target.prototype)` for correct `instanceof` after transpilation; native\nES6+ handles it. Extending `Array` also has subtle `length`\u002Findex behaviors.\n",{"id":61,"difficulty":14,"q":62,"a":63},"abstract-class-pattern","How do you create an abstract class?","JavaScript has no `abstract` keyword, so you simulate it: throw if instantiated\ndirectly (`new.target`) and throw from methods subclasses must implement.\n\n```js\nclass Shape {\n  constructor() {\n    if (new.target === Shape) throw new Error('Shape is abstract')\n  }\n  area() { throw new Error('area() must be implemented') }\n}\nclass Circle extends Shape {\n  constructor(r) { super(); this.r = r }\n  area() { return Math.PI * this.r ** 2 }\n}\n```\n\n`new.target === Shape` blocks direct instantiation; unimplemented methods throw\nat call time. It's a convention, not a language feature.\n",{"id":65,"difficulty":29,"q":66,"a":67},"inheritance-vs-composition-class","When should you prefer composition over class inheritance?","Favor composition when behavior is orthogonal or shared across unrelated types,\nor when a deep hierarchy would become rigid. Use inheritance for genuine is-a\nrelationships with stable base classes.\n\n```js\n\u002F\u002F inheritance forcing a hierarchy\nclass FlyingSwimmingDuck extends Animal {}\n\n\u002F\u002F compose capabilities\nconst duck = { ...canFly(), ...canSwim(), name: 'Donald' }\n```\n\nDeep inheritance suffers from the fragile-base-class problem; composition (mixins,\ndelegation, functions) stays flexible. \"Favor composition over inheritance\"\napplies strongly in JS.\n",{"id":69,"difficulty":14,"q":70,"a":71},"super-property-access","Can super access parent getters and fields?","`super` accesses parent **prototype** members — methods and accessors (getters\u002F\nsetters) — but **not** instance fields (those live on `this`, not the prototype).\n\n```js\nclass A {\n  get label() { return 'A' }\n  x = 1                       \u002F\u002F instance field\n}\nclass B extends A {\n  get label() { return super.label + 'B' }  \u002F\u002F 'AB'\n  getX() { return super.x }                   \u002F\u002F undefined (field, not on proto)\n}\n```\n\nSince `super` looks up the parent prototype, it sees inherited methods\u002Faccessors\nbut not own instance fields, which belong to the instance.\n",{"id":73,"difficulty":14,"q":74,"a":75},"constructor-order","What is the order of initialization in a class hierarchy?","For `new Child()`: the chain of `super()` calls runs **top-down** (parent\nconstructor first), and **fields** initialize right after that level's\n`super()` returns, before the rest of that constructor's body.\n\n```js\nclass A { constructor() { console.log('A ctor'); this.init() } init(){} }\nclass B extends A {\n  x = (console.log('B field'), 1)\n  constructor() { super(); console.log('B ctor') }\n}\n\u002F\u002F new B(): \"A ctor\" -> \"B field\" -> \"B ctor\"\n```\n\nA classic trap: a parent constructor calling an overridable method runs the\nchild override **before** the child's fields are initialized — so the override\nmay see `undefined`.\n",{"id":77,"difficulty":29,"q":78,"a":79},"instanceof-hierarchy","How does instanceof behave across an inheritance hierarchy?","`instanceof` is true for the class and all its ancestors, since each ancestor's\n`prototype` is in the chain.\n\n```js\nclass A {}\nclass B extends A {}\nclass C extends B {}\nconst c = new C()\nc instanceof C   \u002F\u002F true\nc instanceof B   \u002F\u002F true\nc instanceof A   \u002F\u002F true\n```\n\nSo `instanceof` answers \"is-a (or descends-from)\". To check the *exact* class,\ncompare `obj.constructor === C` or `Object.getPrototypeOf(obj) === C.prototype`.\n",{"id":81,"difficulty":14,"q":82,"a":83},"mixin-with-extends","How do you achieve multiple inheritance with classes?","JavaScript allows only single `extends`, so you simulate multiple inheritance\nwith **mixins** — functions that take a base class and return an extended one,\nchained together.\n\n```js\nconst Serializable = (B) => class extends B { serialize() {} }\nconst Comparable  = (B) => class extends B { compareTo() {} }\n\nclass Model extends Serializable(Comparable(Object)) {}\n```\n\nEach mixin wraps the previous class, building a linear chain that combines\nbehaviors. This is the standard pattern for \"implementing multiple interfaces\"\nof behavior in JS.\n",{"id":85,"difficulty":14,"q":86,"a":87},"super-this-binding","What is this when calling super.method()?","`this` stays the **current instance** — `super.method()` runs the parent's\nmethod but with the child instance as `this`, so it operates on the child's data.\n\n```js\nclass A { describe() { return this.constructor.name } }\nclass B extends A {\n  describe() { return super.describe() }   \u002F\u002F parent method, child `this`\n}\nnew B().describe()   \u002F\u002F 'B' — this.constructor is B\n```\n\n`super` changes *which method* runs, not the receiver. That's why an inherited\nmethod can still see the subclass's overridden properties and constructor.\n",{"id":89,"difficulty":14,"q":90,"a":91},"overriding-getter","How do you override a getter or setter in a subclass?","Redefine the accessor in the subclass. Note that defining only a getter (or only\na setter) in the child can **hide** the inherited pair, so redefine both if\nneeded.\n\n```js\nclass A {\n  get value() { return 1 }\n  set value(v) {}\n}\nclass B extends A {\n  get value() { return super.value + 1 }   \u002F\u002F extend\n  \u002F\u002F if you define only the getter, the inherited setter is shadowed away\n}\n```\n\nAccessors are properties, so overriding one member of a get\u002Fset pair replaces\nthe whole property descriptor — define both in the child to keep both behaviors.\n",{"id":93,"difficulty":29,"q":94,"a":95},"protected-convention","Does JavaScript have protected members?","No `protected` keyword. The conventions are: `_underscore` (a hint that it's\n\"internal,\" not enforced) or `#private` (truly private, but **not** accessible\nto subclasses).\n\n```js\nclass Base {\n  _internal = 1   \u002F\u002F convention: subclasses may use, but not enforced\n  #secret = 2     \u002F\u002F private — subclasses CANNOT access this\n}\n```\n\n`#private` is stricter than protected (even subclasses can't see it). For\nsubclass-accessible-but-not-public members, the `_` convention is all JS offers.\n",{"id":97,"difficulty":14,"q":98,"a":99},"calling-overridden-from-parent","Can a parent method call a method overridden by the child?","Yes — method dispatch is dynamic, so a parent method calling `this.foo()` runs\nthe **child's** override if there is one. This is the template-method pattern.\n\n```js\nclass Base {\n  process() { return this.transform(this.read()) }  \u002F\u002F calls overrides\n  read() { return 'data' }\n  transform(x) { return x }\n}\nclass Json extends Base {\n  transform(x) { return JSON.parse(x) }   \u002F\u002F parent's process() uses this\n}\n```\n\nBecause `this` is the actual instance, the inherited `process()` polymorphically\ninvokes the subclass's `transform` — powerful, but watch the constructor-order\ntrap.\n",{"id":101,"difficulty":14,"q":102,"a":103},"super-not-in-arrow","How does super behave inside an arrow function in a method?","An arrow function lexically captures `super` from its enclosing method, so\n`super.x` works inside an arrow defined within a method.\n\n```js\nclass B extends A {\n  greet() {\n    const fn = () => super.greet()   \u002F\u002F super captured lexically\n    return fn()\n  }\n}\n```\n\nLike `this`, `super` is lexical in arrows — it binds to where the arrow is\nwritten. A regular nested function, by contrast, has no `super` binding.\n",{"id":105,"difficulty":14,"q":106,"a":107},"extends-null","What does extends null do?","`class C extends null` creates a class whose instances do **not** inherit from\n`Object.prototype` — like `Object.create(null)` but as a class. It's an edge case\nand tricky (you must manually handle the prototype in the constructor).\n\n```js\nclass NullProto extends null {\n  constructor() { return Object.create(new.target.prototype) }\n}\n```\n\nInstances lack `toString`, `hasOwnProperty`, etc. It's rarely used — mainly for\ncreating prototype-less objects via class syntax. Most code never needs it.\n",{"id":109,"difficulty":29,"q":110,"a":111},"refactor-function-to-class","What changes when refactoring a constructor function to a class?","Mostly cosmetic, but watch the behavioral differences: classes **must** be called\nwith `new`, are **not usable before declaration** (TDZ), run in **strict mode**,\nand have **non-enumerable** methods.\n\n```js\n\u002F\u002F these worked with the function but not the class:\nconst f = MyFunc()        \u002F\u002F -> class: TypeError (needs new)\nnew MyClassUsedAbove()    \u002F\u002F -> ReferenceError (TDZ) if used before declaration\n```\n\nSo code that relied on calling without `new`, hoisting, or sloppy-mode behavior\ncan break. The upside is those were usually bugs the class now catches.\n",{"id":113,"difficulty":29,"q":114,"a":115},"super-multiple-levels","How does super work across multiple inheritance levels?","Each class's `super` refers to its **immediate** parent, so a method can be\nextended at each level and chained via `super`.\n\n```js\nclass A { greet() { return 'A' } }\nclass B extends A { greet() { return super.greet() + 'B' } }\nclass C extends B { greet() { return super.greet() + 'C' } }\nnew C().greet()   \u002F\u002F 'ABC'\n```\n\n`super` is statically bound to the class where the method is defined (its\n`[[HomeObject]]`), not the runtime instance — so multi-level chains resolve\ncorrectly even with overrides.\n",{"id":117,"difficulty":29,"q":118,"a":119},"composition-via-fields","How do you compose behavior by holding instances (has-a)?","Instead of inheriting, a class can **hold** another object and delegate to it —\ncomposition over inheritance.\n\n```js\nclass Engine { start() { return 'vroom' } }\nclass Car {\n  #engine = new Engine()              \u002F\u002F has-a Engine\n  start() { return this.#engine.start() }  \u002F\u002F delegate\n}\n```\n\nThis avoids tight coupling to a base class and lets you swap the held object.\nMany designs that look like inheritance are cleaner as composition with\ndelegation.\n",null,{"description":11},"JavaScript class inheritance interview questions — extends, super, overriding, constructor chaining, polymorphism and extending built-ins.","javascript\u002Fclasses\u002Fclass-inheritance","Inheritance with extends & super","Classes & OOP","classes","2026-06-18","WkrLqBmf4KArV2-vQoIEAb1a75wOTEM9nf9RxS4CGW4",[130,134,135,139],{"subtopic":131,"path":132,"order":133},"Class Syntax & Methods","\u002Fjavascript\u002Fclasses\u002Fclass-syntax",1,{"subtopic":124,"path":20,"order":12},{"subtopic":136,"path":137,"order":138},"Static & Private Members","\u002Fjavascript\u002Fclasses\u002Fstatic-private",3,{"subtopic":140,"path":141,"order":142},"Mixins & Composition","\u002Fjavascript\u002Fclasses\u002Fmixins-composition",4,{"path":144,"title":145},"\u002Fblog\u002Fjavascript-class-inheritance-extends-super","JavaScript Class Inheritance — extends, super, and Method Overriding Explained",1781808676642]