SKU // 54

Object Constructors

An object literal makes one object. When you need many objects with the same shape (thirty students, a hundred products, a deck of cards) you need a way to stamp them out. That is what constructors are for.

// The Problem

const s1 = { name: "Ava", grade: 10, intro() { return `I'm ${this.name}`; } };
const s2 = { name: "Ben", grade: 11, intro() { return `I'm ${this.name}`; } };
const s3 = { name: "Cal", grade: 10, intro() { return `I'm ${this.name}`; } };
// ...copy-paste for every student, and hope you never mistype a key

// Step 1: A Factory Function

The simplest fix is a regular function that builds and returns an object:

function makeStudent(name, grade) {
  return {
    name,
    grade,
    intro() { return `I'm ${this.name}`; }
  };
}

const s1 = makeStudent("Ava", 10);
const s2 = makeStudent("Ben", 11);
console.log(s2.intro());
I'm Ben

// Step 2: A Constructor Function

JavaScript has a built-in pattern for this: a function called with new. Inside it, this is the new object being built:

function Student(name, grade) {
  this.name = name;
  this.grade = grade;
}

const s1 = new Student("Ava", 10);
const s2 = new Student("Ben", 11);

console.log(s1.name, s2.grade);
Ava 11
Convention
Constructor names start with a capital letter (Student, not student). It signals "call me with new."

// What new Does

  1. Creates a brand-new empty object
  2. Sets this inside the function to that object
  3. Runs the function body, which fills in properties
  4. Returns the new object automatically (no return needed)

// Forgetting new

const oops = Student("Dee", 9);   // no new
console.log(oops);                    // undefined
undefined
Watch out
Without new, no object is created and nothing is returned, so oops is undefined. Worse, this inside the call is the global window object, so this.name = name quietly sets window.name to "Dee". In strict mode it throws TypeError: Cannot set properties of undefined instead. The class syntax below prevents this mistake entirely.

// Default Property Values

A constructor can set properties that do not come from arguments. Every object it creates starts with that value:

function Person(first, last) {
  this.firstName = first;
  this.lastName = last;
  this.nationality = "English";    // the same for everyone
}

const myFather = new Person("John", "Doe");
console.log(myFather.nationality);
English

// Adding to One Object vs to All

Adding a property or method to an object that already exists affects only that one object:

const myMother = new Person("Sally", "Rally");

myFather.eyeColor = "blue";         // only myFather gets it
myMother.changeName = function (name) {
  this.lastName = name;             // only myMother gets it
};
console.log(myMother.eyeColor);
undefined

You might expect to add something to every Person by adding it to the constructor itself. That does not work:

Person.eyeColor = "brown";
console.log(myFather.eyeColor);            // still blue: the constructor's own property is not shared

Person.changeName = function (name) { /* ... */ };
myFather.changeName("Smith");
TypeError: myFather.changeName is not a function

Properties added to the constructor function belong to the function, not to the objects it makes. To give every object something new, add it to the constructor's prototype, which is next.

// Sharing Methods with prototype

If you add a method inside the constructor with this.intro = function..., every object gets its own separate copy. Instead, put shared methods on the constructor's prototype: one copy that every object can use:

Student.prototype.intro = function() {
  return `I'm ${this.name}, grade ${this.grade}`;
};

console.log(s1.intro());
console.log(s2.intro());
I'm Ava, grade 10 I'm Ben, grade 11

// The Modern Way: class

The class keyword is a cleaner way to write exactly the same thing. It is what you will see in most current code:

class Student {
  constructor(name, grade) {
    this.name = name;
    this.grade = grade;
  }

  intro() {                    // automatically shared, like prototype
    return `I'm ${this.name}, grade ${this.grade}`;
  }

  promote() {
    this.grade++;
  }
}

const ava = new Student("Ava", 10);
ava.promote();
console.log(ava.intro());
I'm Ava, grade 11
Tip
A class will throw an error if you forget new, which is one of the reasons it is preferred. Classes can do much more (inheritance, private fields) than this course covers; you will see one extra piece, extends, in JS Error Object, where it is used to make custom error types.

// Checking What Made an Object

console.log(ava instanceof Student);   // true
console.log({} instanceof Student);    // false
true false

// Built-in Constructors

JavaScript ships with constructors for all of its native object types. Some you will use constantly:

const today = new Date();        // Dates section
const lookup = new Map();        // Maps section
const unique = new Set();        // Sets section
const err = new Error("Oops");   // Errors section

Others exist but have simpler literal forms that you should use instead:

Instead ofUse
new Object(){}
new Array()[]
new RegExp("abc")/abc/
new Function("a", "return a")a function expression or arrow

Math is not on the list at all: it is a single global object, not a constructor, and new Math() is a TypeError: Math is not a constructor.

Avoid
Do not use new String(), new Number(), or new Boolean(). They create wrapper objects that behave strangely: new Boolean(false) is truthy. Use plain literals ("text", 42, false) instead.

// Quick Check

What does new do when calling new Student("Ava", 10)?

  1. Copies an existing Student
  2. Creates an empty object, sets this to it, runs the function, and returns it
  3. Checks that the arguments are the right types
  4. Makes the function run faster
Show answer
B. Those four steps are the whole job of new. No return is needed in the constructor.

What does this log?

function Dog(name) { this.name = name; }
Dog.prototype.speak = function() { return this.name + " says woof"; };
const d = new Dog("Rex");
console.log(d.speak());
Show answer
Rex says woof. Methods on the prototype are shared by every object the constructor makes, and this is the object the method was called on.

Why is class preferred over a constructor function?

  1. It is the only way to use new
  2. It throws an error if you forget new, and groups the constructor and methods in one clear block
  3. Classes cannot have methods
  4. Constructor functions no longer work
Show answer
B. Both work, but class is clearer and catches the forgotten-new mistake: TypeError: Class constructor Student cannot be invoked without 'new'.

// Try It

  1. Click Open Playground. Finish the factory function makeCar(make, year) and create three cars
  2. Rewrite it as a constructor function Car and create cars with new
  3. Call your constructor without new and see what you get back
  4. Rewrite it as a class Car with an age() method that returns how old the car is
// Video Walkthroughs
Last updated: Oct 10, 2026, 12:53 AM ET