Back to JavaScript
JavaScript
easy
mid

What does the new operator do in JavaScript?

`new F(args)` does four things: (1) create an empty object whose prototype is `F.prototype`, (2) call `F` with `this` bound to the new object, (3) if `F` returns an object, use that; otherwise use the new object, (4) return the result. Powers class instantiation and constructor functions. Arrow functions can't be `new`'d.

3 min read·~6 min to think through

What new actually does

For new F(...args):

  1. Create a fresh object whose internal [[Prototype]] is F.prototype.
  2. Call F with this set to that new object and ...args.
  3. If F explicitly returns an object, the expression evaluates to that object; otherwise it evaluates to the new object.
  4. The result has instance instanceof F === true (because prototype chain).

As a polyfill

js
function myNew(Ctor, ...args) {
  const obj = Object.create(Ctor.prototype);   // step 1
  const result = Ctor.apply(obj, args);        // step 2
  return (result && typeof result === "object") ? result : obj;   // step 3
}

With a class

js
class Foo { constructor(x) { this.x = x; } }
const f = new Foo(1);
f instanceof Foo;             // true
Object.getPrototypeOf(f) === Foo.prototype;  // true

Returning an object overrides

js
function Quirky() { return { custom: true }; }
const q = new Quirky();
q.custom;                     // true
q instanceof Quirky;          // false — we replaced this

Rarely useful; mostly a curiosity. Builder patterns sometimes exploit it.

Forgetting new

js
function Person(name) { this.name = name; }
const p = Person("Sam");      // no new
// In strict mode: TypeError because this is undefined.
// In sloppy: this is globalThis — globalThis.name = "Sam". Disaster.

This is why ES6 class throws if called without new — safer.

Arrow functions can't be new'd

Arrow functions have no [[Construct]] method:

js
const F = () => {};
new F();   // TypeError: F is not a constructor

Same for methods defined with shorthand inside an object literal.

new.target

Inside a constructor, new.target is the function that new was called with (the most-derived class). Useful for:

js
class Abstract {
  constructor() {
    if (new.target === Abstract) throw new Error("Abstract class");
  }
}

When you need new

  • Class instantiation (new MyComponent()).
  • Constructor functions (legacy code).
  • Built-ins: new Date(), new Map(), new Set(), new Promise(), new URL(), new Error().

Some built-ins also work without new (Error("...")); convention varies.

Modern advice

  • Use class so misuse throws.
  • Prefer factory functions (createUser(...)) when you don't need a prototype chain.
  • Don't write function Foo() { this.x = ...} constructor functions in new code.

Interview framing

"new F(args) creates an object whose prototype is F.prototype, calls F with this bound to that object, and returns the new object (unless F returns a different object). The polyfill is Object.create(F.prototype) then F.apply(obj, args). Forgetting new on an ES5 constructor function is a silent disaster — this becomes undefined (strict) or globalThis (sloppy). class solves this by throwing without new. Arrow functions can't be new'd — they have no [[Construct]] internal method. Inside a constructor, new.target is the most-derived class — useful for abstract-class checks."

Follow-up questions

  • Why can't arrow functions be new'd?
  • What does new.target do?
  • Why does class throw without new?

Common mistakes

  • Forgetting new on a constructor function.
  • Returning a non-object expecting it to override.
  • Trying to new an arrow function.

Performance considerations

  • new'd objects share prototype methods (memory efficient). Avoid creating arrow methods on instance if memory is tight.

Edge cases

  • Returning an object overrides the new instance.
  • Built-ins behave differently with vs without new.
  • new.target undefined when not called with new.

Real-world examples

  • new Date(), new URL(), new Map, new Promise, class instantiation everywhere.

Senior engineer discussion

Seniors prefer class over constructor functions, factory functions over class where there's no real prototype to share, and know new.target for abstract patterns.

Related questions