skip to content

Prototypes and Inheritance

JavaScript has no classes underneath: objects delegate to other objects through the prototype chain, and `class` is sugar over that same machinery. Interviewers lean on this area hard because it separates candidates who memorized class syntax from those who know what the engine actually does on every property access.

part ofJavaScriptoverview, primer and where to startread it →
on this pageshow

explore

questions

75 · 5 sections

In JavaScript, how do `'toString' in obj` and `Object.hasOwn(obj, 'toString')` differ for a plain object literal, and when does that difference matter?

level: juniorimportance: must knowfreq 58%
basics
~20 s

The in operator searches the whole prototype chain, so it reports true for inherited names such as toString. Object.hasOwn checks only the object's own properties and reports false. Use hasOwn whenever you mean data the object itself carries.

open as a page

In JavaScript, what does the engine do when you read `obj.x` and `x` is not an own property of `obj`, and what does the assignment `obj.x = 1` do instead?

level: middleimportance: must knowfreq 76%
basics
~20 s

A read walks the prototype chain, checking own properties first and then each prototype in turn, and yields undefined if nothing matches. A plain assignment creates an own property directly on obj, shadowing any inherited property of that name rather than updating it.

open as a page

A JavaScript constructor sets `Ctor.prototype.tags = []`. One instance runs `a.tags.push('x')` and another runs `b.tags = ['y']`. Explain why the two operations have completely different effects.

level: middleimportance: must knowfreq 58%
basics
~20 s

Both instances inherit one array object from the prototype, so push mutates that single shared array and every instance sees the change. Assignment does not touch the prototype: it creates an own tags property on that one instance, which then stops sharing.

open as a page

In JavaScript, given a `base` object that holds shared methods, what is the difference between creating a new object with `Object.create(base)` and creating one with `{ ...base }`?

level: juniorimportance: should knowfreq 60%
basics
~20 s

Object.create(base) returns an empty object linked to base, so every read falls through to base and later edits to base are visible. { ...base } copies base's own enumerable properties once into an unlinked object.

open as a page

In JavaScript, what does the `new` operator actually do when you evaluate `new Person('Ada')`?

level: juniorimportance: must knowfreq 78%
basics
~20 s

The new operator creates a fresh empty object, links its internal prototype to Person.prototype, calls Person with this bound to that object, and then evaluates to that object unless the constructor explicitly returns a different object.

open as a page

How does the JavaScript `instanceof` operator decide its answer, and what exactly does it compare?

level: middleimportance: must knowfreq 78%
basics
~20 s

x instanceof F reads the current value of F.prototype and walks the prototype chain of x, returning true if that exact object appears anywhere in the chain. It compares object identity along a chain, not names, not x.constructor.

open as a page

Given `function Dog(name) { this.name = name; }`, what happens if you call `Dog('Rex')` without `new`, and how does the outcome differ between sloppy mode and strict mode?

level: middleimportance: must knowfreq 60%
basics
~20 s

Without new, Dog runs as a plain function and returns undefined. In sloppy mode this is the global object, so name silently leaks into global state; in strict mode this is undefined and the assignment throws a TypeError immediately.

open as a page

In a JavaScript constructor function invoked with `new`, what happens if the function body explicitly returns an object, and what happens if it returns a primitive such as 42 or null?

level: middleimportance: must knowfreq 62%
basics
~20 s

An object returned from a constructor replaces the freshly created this that new would otherwise hand back. A returned primitive - number, string, boolean, symbol, bigint, null or undefined - is ignored, and new still returns this.

open as a page

In JavaScript, what does an object's `constructor` property refer to, and is it an own property of the instance?

level: juniorimportance: should knowfreq 55%
basics
~10 s

The constructor property is inherited, not own. It sits on the function's prototype object as a non-enumerable property pointing back at that function, and instances reach it by walking the prototype chain.

open as a page

In a JavaScript class, what is the difference between `super(...)` and `super.someMethod()`, and where is each one allowed to appear?

level: juniorimportance: must knowfreq 72%
basics
~20 s

super(...) invokes the parent constructor and is legal only inside the constructor of a class written with extends. super.someMethod() calls the parent's version of a method with the current instance as this, and is legal in any method or accessor.

open as a page

In a JavaScript class body, what does declaring a field as #count = 0 give you that the older convention of naming it _count does not?

level: juniorimportance: must knowfreq 55%
basics
~20 s

A #-prefixed field is privacy enforced by the engine: it can only be named inside the class body that declares it, it is invisible to Object.keys and JSON.stringify, and touching it elsewhere is an error. An underscore name is only a hint.

open as a page

In a JavaScript class, what does the `static` keyword do — which object does the member live on, and can you reach it from an instance?

level: juniorimportance: must knowfreq 72%
basics
~20 s

static installs a method or field on the class constructor itself instead of on instances. You call it as ClassName.member; reading it from an instance gives undefined, because the constructor is not on the instance's prototype chain.

open as a page

In a JavaScript class that uses `extends`, why must the derived constructor call `super()` before it reads or writes `this`, and what happens if it doesn't?

level: middleimportance: must knowfreq 80%
basics
~20 s

A derived constructor does not create its own this: the parent constructor allocates the instance, and super() is what runs it. Until super() returns, this is uninitialized, so reading or writing it throws a ReferenceError.

open as a page

In a JavaScript class body, where do a field declaration like count = 0 and a method declaration like inc() {} each end up at runtime, and what practical differences follow?

level: middleimportance: must knowfreq 60%
basics
~20 s

A class field becomes an own, writable, enumerable, configurable property created on every instance during construction. A method goes once onto the prototype and is shared. So fields appear in Object.keys, spread and JSON output; methods do not.

open as a page

In JavaScript, what do the `get` and `set` keywords do when written inside an object literal or a class body, and how does calling code use the property they create?

level: juniorimportance: must knowfreq 70%
basics
~20 s

get and set define an accessor property: functions the engine runs when code reads or assigns the property with ordinary dot syntax. The getter takes no arguments and returns the value; the setter takes exactly one argument.

open as a page

In JavaScript, which property keys does a `for...in` loop visit that `Object.keys(obj)` does not return, and how do you guard a `for...in` loop against them?

level: juniorimportance: must knowfreq 78%
basics
~20 s

for...in walks the prototype chain and visits inherited enumerable string keys as well as own ones; Object.keys returns only the object's own enumerable string keys. Guard each iteration with Object.hasOwn(obj, key), or iterate Object.keys instead.

open as a page

In JavaScript, what does each of Object.preventExtensions(), Object.seal() and Object.freeze() block on an object, and how do the three relate to one another?

level: juniorimportance: must knowfreq 68%
basics
~10 s

Object.preventExtensions blocks adding properties; Object.seal also blocks deleting and reconfiguring them; Object.freeze additionally blocks writing existing values. Each level includes the previous one, and all three are shallow — nested objects stay mutable.

open as a page

In JavaScript, what does `Object.getOwnPropertyDescriptor(obj, key)` return for a data property versus an accessor property, and which attributes can the two kinds never share?

level: middleimportance: must knowfreq 58%
basics
~10 s

A data property's descriptor has value, writable, enumerable and configurable. An accessor property's has get, set, enumerable and configurable. Every property is exactly one kind, so value/writable and get/set can never appear together.

open as a page

Object.freeze() is described as shallow. What does that mean concretely, and how would you implement a deep freeze that handles an object graph containing cycles?

level: middleimportance: must knowfreq 58%
basics
~20 s

Shallow means only the object's own properties are locked; objects those properties point at stay fully mutable. A deep freeze recurses over own keys and freezes each object value, tracking already-visited objects so a cycle does not recurse forever.

open as a page

In JavaScript, what can wrapping an object in a Proxy do that plain getters and setters cannot, and which real use cases does that unlock?

level: middleimportance: must knowfreq 55%
basics
~20 s

A Proxy intercepts operations on property names that do not exist yet, plus deletes, in-checks, key enumeration and calls, for any target including arrays and functions. Getters and setters only cover properties you declared in advance.

open as a page

JavaScript's Reflect namespace duplicates work that Object.* methods and operators like `in`, `delete` and `new` already do. What is Reflect for, and how does it actually differ from those older APIs?

level: middleimportance: must knowfreq 58%
basics
~20 s

Reflect is a plain namespace object holding one function per internal object operation, matching the Proxy trap list one for one. Unlike the Object.* helpers and operators it mirrors, its methods report failure by returning false and never coerce primitive arguments.

open as a page

In JavaScript, what does `new Proxy(target, handler)` create, what is a trap, and what happens for an operation the handler defines no trap for?

level: juniorimportance: should knowfreq 40%
basics
~20 s

new Proxy(target, handler) returns a new object that routes fundamental operations — property reads, writes, deletes, key listing, calls — to matching handler methods called traps. Any operation whose trap is missing falls through to the target unchanged.

open as a page

A JavaScript Proxy's handler defines an `ownKeys` trap that returns `['a', 'b']`, yet `Object.keys(proxy)` returns an empty array. Which other trap is involved, and why does the result come back empty?

level: middleimportance: should knowfreq 42%
basics
~20 s

Object.keys also calls the getOwnPropertyDescriptor trap for every key that ownKeys reported, to test enumerability. With that trap absent it forwards to the target, which has no such properties, so each key returns undefined and is filtered out.

open as a page

You want arr[-1] to return the last element by wrapping a JavaScript array in a Proxy. What must the get handler do with the property key it receives, and what must it still forward?

level: middleimportance: should knowfreq 35%
basics
~20 s

Property keys reach a get trap as strings or symbols, never numbers, so the handler must convert the key to a number, verify it is a negative integer, and translate it to length plus that index. Everything else must be forwarded unchanged.

open as a page