JavaScript Object Constructors

Object constructors are functions used to create multiple objects with the same structure and behavior. They serve as blueprints for objects. JavaScript provides constructor functions, the new keyword, prototypes, instanceof, Object.create(), and the modern class syntax.

Constructor Functions

A constructor function is a regular function that is designed to be called with the 'new' keyword. By convention, constructor names start with a capital letter. Inside the constructor, 'this' refers to the new object being created.

Constructor Functions
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.greet = function() {
    return `Hi, I'm ${this.name}, ${this.age} years old`;
  };
}

let alice = new Person("Alice", 30);
let bob = new Person("Bob", 25);

console.log(alice.greet());
console.log(bob.greet());
console.log(typeof alice);
console.log(alice.constructor === Person);

The new Keyword

The 'new' keyword does four things: (1) creates a new empty object, (2) sets the prototype of the new object to the constructor's prototype, (3) binds 'this' to the new object and runs the constructor, (4) returns the new object (unless the constructor returns a different object).

What new Does
function Car(brand, model) {
  // 'new' creates {} and sets this = {}
  this.brand = brand;
  this.model = model;
  // 'new' implicitly returns this
}

let car1 = new Car("Toyota", "Camry");
let car2 = new Car("Honda", "Civic");

console.log(car1);
console.log(car2);

// Without 'new', it's just a regular call (BAD!)
// let car3 = Car("Ford", "Focus");
// console.log(car3); // undefined! 'this' was global

// Simulating what 'new' does internally
function simulateNew(Constructor, ...args) {
  let obj = Object.create(Constructor.prototype);
  let result = Constructor.apply(obj, args);
  return result instanceof Object ? result : obj;
}

let car3 = simulateNew(Car, "Ford", "Focus");
console.log(car3);

Prototype Chain Basics

Every function has a prototype property. When you create an object with 'new', the object's internal prototype links to the constructor's prototype. This allows shared methods to live on the prototype instead of being duplicated on every instance.

Prototype Methods
function Animal(name, sound) {
  this.name = name;
  this.sound = sound;
}

// Shared method on the prototype
Animal.prototype.speak = function() {
  return `${this.name} says ${this.sound}!`;
};

Animal.prototype.type = "Animal";

let dog = new Animal("Rex", "Woof");
let cat = new Animal("Whiskers", "Meow");

console.log(dog.speak());
console.log(cat.speak());

// Method is shared, not duplicated
console.log(dog.speak === cat.speak);

// Instance property vs prototype property
console.log(dog.hasOwnProperty("name"));
console.log(dog.hasOwnProperty("speak"));

instanceof and Object.create()

The instanceof operator checks if an object was created by a specific constructor (or has it in its prototype chain). Object.create() creates a new object with a specified prototype, allowing prototypal inheritance without constructors.

instanceof and Object.create()
function Shape(type) {
  this.type = type;
}

let circle = new Shape("circle");

console.log(circle instanceof Shape);
console.log(circle instanceof Object);
console.log("hello" instanceof Shape);

// Object.create() — create with specific prototype
let personProto = {
  greet() {
    return `Hi, I'm ${this.name}`;
  }
};

let alice = Object.create(personProto);
alice.name = "Alice";
alice.age = 30;

console.log(alice.greet());
console.log(Object.getPrototypeOf(alice) === personProto);

// Object with no prototype
let bare = Object.create(null);
bare.x = 1;
console.log(bare.x);
// bare has no toString, valueOf, etc.

Class Syntax Preview

ES6 classes provide a cleaner syntax for constructor functions and prototypes. Under the hood, classes are still functions and prototypes — they are 'syntactic sugar'. Classes make constructor patterns more readable and familiar.

Class Syntax
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greet() {
    return `Hi, I'm ${this.name}`;
  }

  getAge() {
    return this.age;
  }
}

let alice = new Person("Alice", 30);
let bob = new Person("Bob", 25);

console.log(alice.greet());
console.log(bob.getAge());
console.log(alice instanceof Person);

// Classes are functions under the hood
console.log(typeof Person);
console.log(alice.greet === bob.greet);
ApproachSyntaxBest For
Constructor functionfunction Foo() { this.x = 1 }Traditional pattern
Prototype methodsFoo.prototype.bar = fnShared methods
new keywordnew Foo()Creating instances
instanceofobj instanceof FooType checking
Object.create(proto)Object.create(parent)Prototypal inheritance
classclass Foo { constructor() {} }Modern, clean syntax
📝 Note: Always use 'new' when calling constructor functions. Without 'new', 'this' will refer to the global object (or undefined in strict mode), causing unintended side effects. ES6 classes enforce 'new' automatically and throw an error if called without it.
Exercise:
What does the 'new' keyword do first when calling a constructor?
Try it YourselfCtrl+Enter to run
Click Run to see the output here.