skip to content

Constructor Functions and new

The pre-class way of stamping out objects, and the semantics that `class` still inherits: what the `new` operator does step by step, how a constructor can subvert it, and how an instance points back at the function that built it.

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

explore

questions

13

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

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

Why does `new (() => {})()` throw a TypeError in JavaScript, and which other function forms are non-constructible in the same way?

level: juniorimportance: should knowfreq 45%

basics

~20 s

Arrow functions are callable but not constructible: they have no [[Construct]] internal method and no prototype property, so new throws a TypeError. Concise object and class methods, getters and setters, generator functions and async functions are non-constructible too.

open as a page

After writing `Child.prototype = Object.create(Parent.prototype)`, what does `new Child().constructor` return, and how do you repair it correctly?

level: middleimportance: should knowfreq 50%

basics

~10 s

It returns Parent. Replacing the prototype object throws away the constructor that pointed at Child, so lookup continues up the chain. Repair it with Object.defineProperty, which keeps the property non-enumerable, rather than plain assignment.

open as a page

What is `new.target` inside a JavaScript function, and how do you use it to guard a constructor against being called without `new`?

level: middleimportance: should knowfreq 44%

basics

~20 s

new.target is a meta-property readable inside a function body: it is undefined when the function was called normally and holds the constructor that was invoked when it was constructed. Guards test it to throw, or to re-invoke construction automatically.

open as a page

Inside a JavaScript class declared with `extends`, what values may its constructor return, and how do those rules differ from a class that extends nothing?

level: middleimportance: should knowfreq 32%

basics

~20 s

A derived constructor may return only an object or undefined; returning any other value, including null, throws a TypeError. A base constructor is looser - it ignores every primitive return, including null, and simply hands back its instance.

open as a page

An array handed to your code from a same-origin `<iframe>` fails `value instanceof Array`. Explain why, and how you would make the check reliable.

level: seniorimportance: should knowfreq 40%

basics

~20 s

Each realm has its own set of built-ins, so the iframe's Array is a different function object with a different Array.prototype. The value's chain holds the iframe's prototype, so the identity comparison fails. Use Array.isArray, which is realm-independent.

open as a page

How would you implement JavaScript's `new` operator yourself as a function `myNew(Fn, ...args)`, and what can that hand-rolled version not reproduce?

level: seniorimportance: should knowfreq 36%

basics

~20 s

Create an object with Object.create(Fn.prototype), invoke Fn.apply on it with the arguments, and hand back that object unless the call produced an object of its own. The imitation still cannot set new.target or construct class constructors.

open as a page

What does `Symbol.hasInstance` do to the `instanceof` operator, and why does `fn[Symbol.hasInstance] = handler` usually fail to take effect?

level: middleimportance: nice to knowfreq 22%

basics

~10 s

Symbol.hasInstance is the hook instanceof calls first: if the right-hand operand has that method, its boolean result is the answer and no prototype chain is walked. Plain assignment fails because Function.prototype[Symbol.hasInstance] is non-writable.

open as a page

A JavaScript constructor function stores its first instance on a property of itself and returns that stored object on every later call, so `new Config()` always yields the same object. How does that work, and what problems does it cause in production code?

level: seniorimportance: nice to knowfreq 28%

basics

~20 s

It exploits the rule that an object returned from a constructor replaces the freshly built this, so every call after the first hands back the cached instance. The costs are silently ignored constructor arguments, hidden global state that tests cannot reset, and subclasses that receive the base instance instead of their own.

open as a page