Prompt
Create a constructor function Person(name, age) that sets both properties on the instance
and adds a sayHello method on the prototype (shared across all instances, not per-instance).
Solution
This is the pattern class desugars to, and interviewers ask it because debugging any class hierarchy eventually means reasoning at this level. What new Person('Bob', 30) actually does, in four steps: creates a fresh object whose internal prototype link points at Person.prototype; binds that object as this; runs the constructor body, which stamps per-instance data onto this; returns the object (unless the constructor explicitly returns another object — a rarely-used escape hatch worth knowing exists).
The design decision the tests verify: sayHello lives on the prototype, so one function object serves every instance — a.sayHello === b.sayHello is true, and hasOwnProperty('sayHello') is false because method lookup walks the prototype chain rather than finding it on the instance. Define methods inside the constructor instead and every new allocates a fresh closure per method — ten thousand instances means ten thousand copies of identical code. Data on the instance, behavior on the prototype: that's the split, and it's exactly what class syntax generates.
The trade-off cuts the other way when you need closure-based privacy (see the counter factory) — prototype methods can only see this, never the constructor's local variables.
Red flag: assigning this.sayHello = function() {...} inside the constructor "so it's all in one place." That's the memory-per-instance mistake, and it also breaks the shared-identity check an interviewer will run.
Say it: "new links a fresh object to the constructor's prototype and binds it as this — I keep data on instances and methods on the prototype, which is exactly what class syntax compiles to."