AlgoInsight

Free lesson · JavaScript Basic to Advance

Interview Lens: Objects and Prototypes

Easy5 min read

The Question

Object and prototype questions cluster around four patterns interviewers cycle through:

"How does prototypal inheritance work in JavaScript?"

"What's the difference between value types and reference types?"

"Implement your own new operator." Or Object.create. Or a deep clone.

Some output-prediction puzzle involving prototype chains, shadowing, or reference equality.

These come up constantly in JavaScript interviews — slightly less often than closures, but with similar weight at senior levels. The interviewer wants to know whether you understand JavaScript's object model deeply or whether you've just learned to use objects without understanding their mechanism.

Arun on the interview psychology. Nikhil on the technical depth — prototypes are the area where senior interviewers most often probe past surface answers into engine-level material.

Why They Ask It

Objects and prototypes are JavaScript's object model. Almost everything in the language is built on them — arrays, functions, classes, the DOM. A candidate who doesn't understand prototypes can use objects, but they can't reason about them. When something goes wrong — a method behaves unexpectedly, an instance shares state it shouldn't, an instanceof check fails — they don't know where to look.

Three signals interviewers listen for:

Signal 1: Do you understand the difference between values and references? This is the foundational question. A candidate who says "objects are copied by reference" when they mean "objects are referenced, not copied" is signaling fuzzy understanding. A candidate who can articulate why {a: 1} === {a: 1} is false and what that means for function arguments has the model right.

Signal 2: Can you trace through a prototype chain? Given a small inheritance structure, can you predict what child.someMethod() will do? Where does the method come from? What is this inside? Tracing carefully under pressure is the senior skill.

Signal 3: Do you understand classes as syntactic sugar? Senior interviews probe whether you know that classes (Module 8) are built on prototypes. A candidate who treats classes as a separate mechanism — different from prototypal inheritance — signals they've memorized the syntax without understanding what's underneath.

The first time I (Arun) was asked to implement new from scratch was at an interview about a year out of college. I knew what new did at the conceptual level — creates an object, calls the function as a constructor. But I'd never thought about implementing it. I fumbled through it. Got most of it right with hints. The interviewer didn't seem impressed, and I didn't get the offer.

I went home that night and wrote my own new ten different ways. Different signatures, different edge cases. The next interview that asked about it, I aced. The pattern: don't just use JavaScript features. Build them. Once you've built new, Object.create, and a few similar things from scratch, JavaScript's object model stops feeling mysterious.

The Wrong Answers

Warning: The object mistakes interviewers see most often.

"JavaScript objects are passed by value." They're not. Objects are passed by reference — or more precisely, the reference is passed by value, which means the function receives a copy of the reference but both references point to the same object. This phrasing is sometimes called "pass by reference value" or "pass by sharing." Saying "by value" suggests the function gets its own copy of the data, which is wrong.

"Prototypal inheritance is the same as classical inheritance." It isn't. In classical inheritance, classes are templates that instances are created from. In prototypal inheritance, prototypes are live objects that instances inherit from directly. The difference matters because in JavaScript, you can modify a prototype after instances are created and they'll see the changes — something you can't do with classical classes.

"Classes in JavaScript are real classes." Not at the runtime level. They're syntactic sugar over the prototype mechanism. class User { greet() {} } is essentially equivalent to function User() {}; User.prototype.greet = function() {};. Knowing this distinction is important — when a class behaves unexpectedly, the explanation is usually at the prototype level, not the class level.

"for...in and Object.keys are the same." They're not. for...in walks the prototype chain and includes inherited enumerable properties. Object.keys returns only own enumerable properties. The distinction has real consequences when working with inheritance.

The Right Answer

Three layers depending on the depth of the question.

The 30-Second Answer

For "what is prototypal inheritance?":

"Every JavaScript object has a hidden link to another object, its prototype. When you access a property on an object, if it's not found, JavaScript looks at the prototype, then the prototype's prototype, until either the property is found or the chain ends at null. This is how inheritance works in JavaScript. Methods can be defined once on a prototype and shared across many instances."

For "value vs reference types":

"Primitives — numbers, strings, booleans, null, undefined, symbols, bigint — are copied by value. Objects, arrays, and functions are referenced. Assigning an object to a new variable creates another reference to the same object, not a new object. Modifying through either reference is visible through both."

Interactive animation: Answer by walking, not defining - the lookup hops from the array to Array.prototype, then Object.prototype.

The 2-Minute Answer

Build on the above:

"In practice, prototypal inheritance is what makes JavaScript memory-efficient at scale. If you have ten thousand user objects, they all share the same method implementations through their prototype — you don't have ten thousand copies of greet. This is also why modifying a prototype affects all instances using it: there's only one prototype object, and they all link to it.

Classes in modern JavaScript are syntactic sugar over this mechanism. class User { greet() {} } creates a User function and attaches greet to User.prototype. New users created with new User() get linked to that prototype. The behavior is identical to using Object.create or the older constructor-function pattern. The class syntax is just cleaner.

The reference type distinction matters for function arguments. When you pass an object to a function, the function gets a reference to your object. Modifying properties on that reference modifies your original object. This is why it's good practice to either avoid mutating arguments or be very explicit when you're doing so."

Interactive animation: The four rules every object quiz tests - each traced from the rule to what it prints.

The Deep Dive (Nikhil's territory)

For senior or staff interviews probing deeper:

"At the engine level, every object stores a hidden field — the internal [[Prototype]] slot — that points to its prototype. The chain is implemented as a linked list of these pointers. Property access walks this list, checking each object in turn. When the engine creates a new object with Object.create(proto) or new Constructor(), it sets this slot to the appropriate prototype.

Function objects have an additional property: .prototype. This is not the function's own prototype — it's the object that will become the prototype of instances created by new Function(...). The naming is confusing, but the distinction is precise. Function.prototype is what Function's instances inherit from; Function's own prototype is Function.prototype (because functions are objects too, and the function's [[Prototype]] points to Function.prototype as well).

instanceof works by walking up the prototype chain and checking whether the constructor's .prototype appears anywhere. So obj instanceof Array returns true if Array.prototype is in obj's chain.

The reference semantics are sometimes described as 'pass by reference value' — the reference is passed by value, so the function gets its own copy of the reference, but both copies point to the same object. This is why function modify(obj) { obj = {} } doesn't change the caller's object: it reassigns the local reference, leaving the caller's reference (and the original object) intact. But function mutate(obj) { obj.x = 5 } does affect the caller's object because both references point to the same memory."

Implement new: The Classic Challenge

A common interview challenge: "Implement the new operator from scratch."

function myNew(constructor, ...args) {
  // Step 1: Create a new object with the constructor's prototype
  const obj = Object.create(constructor.prototype);

  // Step 2: Call the constructor with 'this' bound to the new object
  const result = constructor.apply(obj, args);

  // Step 3: If the constructor returned an object, return that; otherwise return the new object
  return (typeof result === "object" && result !== null) ? result : obj;
}

function User(name, age) {
  this.name = name;
  this.age = age;
}

User.prototype.greet = function() {
  return `Hi, I'm ${this.name}`;
};

const olena = myNew(User, "Olena", 35);
console.log(olena.name);          // "Olena"
console.log(olena.greet());       // "Hi, I'm Olena"
console.log(olena instanceof User);   // true

Walk through it out loud:

"new does four things. First, it creates a new empty object with its prototype linked to the constructor's .prototype. Second, it calls the constructor function with this bound to that new object. Third, if the constructor returns an object, use that; otherwise use the new object we created. Fourth, return the result.

Object.create(constructor.prototype) handles the first step. constructor.apply(obj, args) handles the second — apply lets us call a function with a specific this. The third step is the edge case people forget: constructors can return objects, and when they do, new returns that object instead of the implicit this."

The interviewer might extend: "Can you implement Object.create from scratch?" That's a one-liner once you understand prototypes:

function myObjectCreate(proto) {
  function F() {}
  F.prototype = proto;
  return new F();
}

const animal = { eats: true };
const dog = myObjectCreate(animal);
console.log(dog.eats);   // true

Create an empty function, set its prototype to the desired prototype, return a new instance. This is essentially the polyfill Object.create had in old environments.

Interactive animation: Object.create, from scratch - an empty function, its prototype set, and a new instance returned.

The Follow-Ups

Interview: What the interviewer asks next once you've answered well.

"What does new actually do?" Four steps: create object, set prototype, call function with this bound, return object (or constructor's returned object).

"What's the difference between __proto__ and .prototype?" __proto__ (or Object.getPrototypeOf(obj)) is the prototype of an instance. .prototype is a property of functions, used when those functions are called with new — it becomes the prototype of created instances.

"Why is modifying built-in prototypes considered bad practice?" It affects every instance of that type across the entire program, including ones in libraries. Risk of collision with future spec additions. Hard to reason about.

"How would you do a deep clone of an object?" Several approaches: structuredClone (modern native), JSON.parse(JSON.stringify(obj)) (works but limited — no functions, no dates correctly), or recursive cloning. Each has trade-offs.

"What's the difference between Object.freeze and const?" const prevents reassigning the variable. Object.freeze prevents modifying the object's contents. Different mechanisms operating on different things.

The Founder Moment

Nikhil here. The prototype question that taught me the most was at my third Google interview — the one I eventually didn't get an offer from. Late in the loop, an engineer asked me "what's Function.prototype.prototype?" I paused. The double .prototype looked like a trick question.

I worked through it out loud. Function.prototype is the object that functions inherit from — it's where bind, call, and apply live. So Function.prototype.prototype would be... wait, does Function.prototype itself have a .prototype property? Let me think. .prototype is the special property on function objects that becomes the prototype of new instances. Function.prototype is itself a function (specifically, a do-nothing function). So Function.prototype.prototype is the prototype that instances of Function.prototype would receive if you called it with new. Which is Object.prototype. So the answer is Object.prototype.

I gave that answer haltingly, walking through the logic. The interviewer nodded. Said "yeah, that's right, took you a minute though." I didn't get the offer (system design round was where I bombed), but I left that interview understanding prototypes more deeply than I had going in.

What I took from that: the hardest interview questions aren't testing whether you know an answer. They're testing whether you can derive one from the model. If you understand prototypes precisely — what each property is, where each function lives, how the chain forms — then any question, even one with weird double-.prototype syntax, is just an exercise in walking the chain carefully.

Master the model. The questions take care of themselves.

Back to JavaScript Basic to Advance