Constructor, operator "new"

Object literals with {...} are perfect when you need a single object. The trouble starts when you need twenty of them that all share the same shape: a list of users, a set of menu items, a cart full of products. Copy-pasting a literal twenty times is tedious and easy to get wrong.

JavaScript’s answer is the pair of tools we’ll unpack here: constructor functions and the new operator. Together they act like a stamp — write the shape once, then press out as many objects as you want.

Constructor function

A constructor is nothing exotic. It’s an ordinary function. What makes it a “constructor” is a pair of conventions the community agreed on:

  1. Name it with a capital first letter. Member, not member. This is a signal to whoever reads the code, not a rule the engine enforces.
  2. Call it with new. That’s the switch that turns a plain function call into object creation.

Here’s the canonical example:

function Member(name) {
  this.name = name;
  this.isPremium = false;
}

let member = new Member("Kira");

alert(member.name); // Kira
alert(member.isPremium); // false

Notice the function never returns anything explicitly, yet user ends up as a fully-formed object. The new keyword is doing work behind the scenes.

What new actually does

When you put new in front of a function call, three steps run automatically:

  1. A fresh empty object is created and bound to this.
  2. The function body runs. Typically it hangs properties off this.
  3. this is returned as the result of the whole new expression.
1
this = {}  // new empty object
2
this.name = “Kira”  // body runs
3
return this  // implicit
The three steps new performs, in order.

So new Member("Kira") behaves as if the body were written like this, with the commented lines happening for you:

function Member(name) {
  // this = {};  (implicitly)

  // add properties to this
  this.name = name;
  this.isPremium = false;

  // return this;  (implicitly)
}

Which means let member = new Member("Kira") produces exactly the same object you’d get by writing the literal by hand:

let member = {
  name: "Kira",
  isPremium: false
};

The payoff is reuse. Want more members? new Member("Priya"), new Member("Nadia"), and on it goes. Each call runs the same steps against a fresh object, so you get consistent results with far less typing than repeating a literal every time.

kira{name:"Kira", isPremium:false}
priya{name:"Priya", isPremium:false}
Two separate objects, each built by its own new Member(...) call. They share a shape, not a reference.

That reuse is the whole point of a constructor: one place that defines how an object gets built. Type a name and press the button below to stamp out a fresh object from the same Member blueprint each time — every click runs the three steps against a new this.

interactiveStamp out members from one blueprint

Constructor mode test: new.target

Inside a function you can detect whether it was invoked with new by reading a special new.target property. It’s undefined for a plain call and holds the function itself when called with new:

function Member() {
  alert(new.target);
}

// without "new":
Member(); // undefined

// with "new":
new Member(); // function Member { ... }
Member()
new.target ==> undefined
regular mode
new Member()
new.target ==> Member
constructor mode
new.target is your switch for detecting how the function was called.

One practical use: make the function behave the same whether or not the caller remembered new. If someone forgets it, you quietly redirect:

function Member(name) {
  if (!new.target) { // called without new?
    return new Member(name); // ...add new for the caller
  }

  this.name = name;
}

let maya = Member("Maya"); // redirects to new Member
alert(maya.name); // Maya

Some libraries do this so their API is forgiving. Use it sparingly, though. When new is present, everyone reading the code knows an object is being constructed. Hide that behind an auto-correct and the intent gets murkier.

Return from constructors

Most constructors have no return at all. They write everything into this, and this becomes the result on its own. But a return statement is legal inside a constructor, and it follows one small rule:

  • return with an object replaces this — that object comes back instead.
  • return with a primitive (or an empty return) is ignored — this still comes back.
return { … }
==>
that object wins
return 42  /  return;
==>
this wins
(no return)
==>
this wins
How the return value of a constructor is decided.

Here a returned object overrides this:

function BigMember() {

  this.name = "Maya";

  return { name: "Titan" };  // <-- returns this object
}

alert( new BigMember().name );  // Titan, got that object

And here an empty return changes nothing — you’d get the same result with a primitive after return:

function SmallMember() {

  this.name = "Maya";

  return; // <-- returns this
}

alert( new SmallMember().name );  // Maya

You’ll rarely lean on this. It’s here so nothing surprises you later — for example, when you read a constructor that returns a cached instance instead of a fresh one.

Try both branches below. Flip the switch to choose what the constructor returns, then build it — an object return wins, while a primitive return is ignored and you get this back instead.

interactiveWhat does the constructor hand back?

Methods in constructor

Constructors give you a lot of room. The parameters decide what goes into each object, so different arguments produce differently-configured instances from the same blueprint.

And this isn’t limited to data. You can attach functions too, giving each object its own methods.

Here new Member(name) builds an object that carries both a name and a greet method:

function Member(name) {
  this.name = name;

  this.greet = function() {
    alert( "My name is: " + this.name );
  };
}

let maya = new Member("Maya");

maya.greet(); // My name is: Maya

/*
maya = {
   name: "Maya",
   greet: function() { ... }
}
*/
maya
name:
“Maya”
greet:
function() { … }
The object maya holds a data property and a method, both set up by the constructor.

Each object built this way carries its own greet, and inside that method this points at the object it belongs to. Build a couple of users below and greet them — every greeting reports the name of the object whose method you called.

interactiveGive each object its own method

For richer object modeling, there’s a more polished syntax — classes — that we’ll get to later. It’s built on top of the same machinery you just learned.

Summary

  • Constructor functions are ordinary functions, distinguished by a naming convention: a capital first letter.
  • They’re meant to be called with new. That call creates an empty this up front, runs the body, and returns the filled-in object at the end.

Constructors exist to stamp out many similar objects from one definition. JavaScript itself ships plenty of built-in constructors you’ll meet as you go — Date for dates, Set for collections of unique values, Map, and more, all invoked with new.