skip to content

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

level: juniorimportance: must knowfreq 78%

answer

  1. four steps, in order
  2. object exists before the body runs
  3. link, not a copy
  4. the prototype comes from Fn.prototype
  5. result is the object unless overridden

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.

solid answer

~40 s

`new Person('Ada')` does four things. First it creates a brand-new ordinary object. Second it sets that object's internal prototype (its `[[Prototype]]`, what `Object.getPrototypeOf` reports) to the current value of `Person.prototype` — so the instance delegates to everything hanging off `Person.prototype`. Third it invokes `Person` with `this` bound to the new object and `'Ada'` as the argument, which is why `this.name = name` in the body puts a property on the instance. Fourth, the whole expression evaluates to that new object, unless the constructor returned some other object explicitly. Two details worth saying out loud: the prototype link is a live reference to the object `Person.prototype` currently points at, not a copy of its properties; and if `Person.prototype` is not an object at that moment, the engine falls back to `Object.prototype`.

go deeper

for a junior

Be ready to list the steps in order — create an object, link it to the function's prototype, run the body with this bound to it, hand it back — and to point at the line in a constructor where an own property gets created.

for a middle

Explain that the prototype link is a live reference rather than a copy, so methods added to the prototype later are visible on instances built earlier, and that replacing the prototype object leaves existing instances behind.

for a senior

Show the memory and design consequence: shared behaviour on the prototype means one function object for thousands of instances, whereas closing over constructor state forces a per-instance allocation. Say when each is the right trade.

for a principal

Frame it as an API decision — whether your library exposes a new-able constructor at all, versus a plain factory that returns configured objects, and what that choice costs consumers in subclassability, instance checks, and refactoring freedom.

## What `new` is `new` is an operator, not a function call with extra decoration. Written `new Fn(arg1, arg2)`, it asks the function `Fn` to construct something: the language runs `Fn`'s internal construct behaviour rather than its plain call behaviour. Everything below describes that construct behaviour for an ordinary function declared with `function`. ## The four steps Evaluating `new Person('Ada')`: 1. **Create** a new ordinary object — empty, with no own properties. 2. **Link** it: set that object's internal prototype slot (`[[Prototype]]`) to the value of `Person.prototype` at this moment. 3. **Call** `Person` with `this` bound to the new object and the argument list `('Ada')`. 4. **Result**: the expression evaluates to the new object, unless the call returned an object of its own, in which case that object wins. ```js function Person(name) { this.name = name; // step 3: `this` is the new object } Person.prototype.greet = function () { return `Hi, ${this.name}`; }; const p = new Person('Ada'); p.name; // 'Ada' — own property, put there in step 3 Object.getPrototypeOf(p) === Person.prototype; // true — step 2 p.greet(); // 'Hi, Ada' — found by delegation, not copied ``` ## Step 1 and 2: creation and the prototype link The object is created *before* the body runs, which is why `this` already exists on the constructor's first line. The link established in step 2 is what makes the instance behave like a `Person`: `p` has no `greet` of its own, but a property read that misses on the object continues along the prototype link and finds `greet` on `Person.prototype`. The link is a **reference to an object**, not a snapshot of its contents. Add a method to `Person.prototype` after `p` exists and `p` can call it immediately, because `p` points at the same object you just mutated: ```js Person.prototype.shout = function () { return this.name.toUpperCase(); }; p.shout(); // 'ADA' — works on an instance created earlier ``` The opposite is also true and surprises people: *replacing* `Person.prototype` with a whole new object does not retroactively re-link existing instances. `p` still points at the old object; only instances created after the reassignment get the new one. ## The `Person.prototype` fallback Step 2 reads `Person.prototype` and requires an object. If it is a primitive or `null` — someone wrote `Person.prototype = 42` or `null` — the engine does not throw; it links the new object to the built-in `Object.prototype` instead: ```js function F() {} F.prototype = 42; Object.getPrototypeOf(new F()) === Object.prototype; // true ``` This is a small piece of trivia that reveals whether someone has actually read what the operator does or is reciting a blog summary. ## Step 3: `this` inside the body During the construct call, `this` is the freshly created object — not the function, not the global object, not `Person.prototype`. Anything the body assigns to `this` becomes an **own** property of the instance, which is exactly why per-instance state goes on `this` and shared behaviour goes on `Person.prototype`: methods placed on the prototype exist once, whereas a function assigned to `this` inside the body is re-created for every instance. ## Step 4: the result With no `return` statement — the normal case — the expression is the new object. A constructor body that ends without returning anything still produces the instance, so `return this;` at the end of a constructor is redundant, not required. (A constructor that deliberately returns *another* object overrides the result; that is a rule in its own right.) ## Syntax details that come up `new Person` with no argument list is legal and identical to `new Person()`. Precedence matters when a member access is involved: `new Foo.bar()` reads `Foo.bar` first and constructs *that*, while `new Foo().bar` constructs `Foo` and then reads `bar` off the instance. When in doubt, add the parentheses. ## Why interviewers ask this The four steps are the smallest complete model of object creation in JavaScript, and almost every downstream question depends on them: why methods live on `prototype`, why a forgotten `new` corrupts state, why one function can serve as a factory for thousands of objects that share one method object. Being able to recite the steps *in order* — create, link, call with `this`, return — and to name what each one buys you is the whole answer.

  • If I reassign `Person.prototype = { greet() {} }` after some instances already exist, what happens to those instances?
    Nothing — they keep pointing at the object that was `Person.prototype` when they were constructed. The link is fixed at construction time, so old instances still delegate to the old prototype object and will not see methods added to the replacement. Only objects created after the reassignment get the new prototype.
  • What is the difference between putting a method on `this` inside the constructor and putting it on `Person.prototype`?
    A method assigned to `this` becomes an own property, so a separate function object is allocated per instance and it shadows anything with the same name further along the prototype chain. A method on `Person.prototype` exists once and is shared by every instance through delegation. Per-instance functions are only worth it when the function must close over constructor-local state.
  • Is `new Foo.bar()` the same as `new Foo().bar`?
    No. `new Foo.bar()` evaluates the member access first and constructs `Foo.bar`, so `Foo.bar` had better be a constructor. `new Foo().bar` constructs `Foo` and then reads the `bar` property off the resulting instance. The two parse completely differently, which is a good reason to always write the argument parentheses explicitly.

saying these in an interview costs you the question

  • Says new copies the properties from Fn.prototype onto the instance
  • Thinks the instance's prototype is set to the constructor function itself
  • Claims the constructor must end with return this to work
  • Says this inside the constructor refers to the function object
  • Believes new creates the object only after the body finishes

context