Skip to main content

JavaScript Object Constructors

Introduction

In JavaScript, we often need to create multiple objects with similar properties and methods. While we could create each object individually using object literals, this approach becomes repetitive and inefficient when dealing with many similar objects.

This is where object constructors come in. A constructor is essentially a function that serves as a blueprint for creating objects with predefined properties and methods. It allows us to create multiple instances of similar objects without duplicating code.

Understanding Object Constructors

What is an Object Constructor?

An object constructor is a function that is used with the new keyword to create new objects. The constructor function defines the properties and behaviors that will belong to the new object.

Let's start with a simple example to see how constructors work:

javascript
// Constructor function
function Person(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

// Creating objects using the constructor
const person1 = new Person("John", "Doe", 30);
const person2 = new Person("Jane", "Smith", 25);

console.log(person1);
// Output: Person {firstName: "John", lastName: "Doe", age: 30}

console.log(person2);
// Output: Person {firstName: "Jane", lastName: "Smith", age: 25}

In this example:

  • We created a Person constructor function
  • We used the new keyword to create multiple instances of Person objects
  • Each object has its own values for firstName, lastName, and age

The this Keyword in Constructors

Inside a constructor function, the this keyword refers to the new object being created. It's how we assign properties to the new object.

When you use the new keyword with a constructor function:

  1. A new empty object is created
  2. The function is called with this set to the new empty object
  3. The object is returned automatically (unless the constructor explicitly returns a different object)

Adding Methods to Constructors

We can also add methods to our objects using constructor functions:

javascript
function Person(firstName, lastName, age) {
// Properties
this.firstName = firstName;
this.lastName = lastName;
this.age = age;

// Method
this.getFullName = function() {
return this.firstName + " " + this.lastName;
};
}

const person1 = new Person("John", "Doe", 30);

// Calling the method
console.log(person1.getFullName());
// Output: "John Doe"

Constructor Function Naming Convention

By convention, constructor function names start with a capital letter (like Person instead of person). This helps distinguish constructor functions from regular functions and serves as a visual cue that these functions should be used with the new keyword.

The Prototype Pattern

While the basic constructor approach works, it has a drawback: each object created gets its own copy of the methods, which is memory inefficient. To solve this problem, JavaScript provides the prototype mechanism.

javascript
function Person(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

// Add method to the prototype
Person.prototype.getFullName = function() {
return this.firstName + " " + this.lastName;
};

const person1 = new Person("John", "Doe", 30);
const person2 = new Person("Jane", "Smith", 25);

console.log(person1.getFullName()); // "John Doe"
console.log(person2.getFullName()); // "Jane Smith"

With this approach, the getFullName method exists only once in memory (in the Person.prototype object) rather than being duplicated for each Person instance.

Checking Instance Types

You can check if an object is an instance of a constructor using the instanceof operator:

javascript
function Person(name) {
this.name = name;
}

const person1 = new Person("John");
const regularObject = { name: "Jane" };

console.log(person1 instanceof Person); // Output: true
console.log(regularObject instanceof Person); // Output: false

Constructor Property

Every JavaScript object has a constructor property that refers to the function that created it:

javascript
function Person(name) {
this.name = name;
}

const person1 = new Person("John");
console.log(person1.constructor === Person); // Output: true

Practical Example: Creating a Library System

Let's build a simple book tracking system using object constructors to see how they can be useful in a real-world application:

javascript
// Book constructor
function Book(title, author, pages, genre) {
this.title = title;
this.author = author;
this.pages = pages;
this.genre = genre;
this.isAvailable = true;
}

// Add methods to Book prototype
Book.prototype.checkout = function() {
if (this.isAvailable) {
this.isAvailable = false;
return `${this.title} has been checked out.`;
} else {
return `${this.title} is not available for checkout.`;
}
};

Book.prototype.returnBook = function() {
if (!this.isAvailable) {
this.isAvailable = true;
return `${this.title} has been returned.`;
} else {
return `${this.title} was not checked out.`;
}
};

// Library constructor
function Library(name) {
this.name = name;
this.books = [];
}

// Add methods to Library prototype
Library.prototype.addBook = function(book) {
if (book instanceof Book) {
this.books.push(book);
return `${book.title} added to ${this.name}.`;
} else {
return "Only Book objects can be added.";
}
};

Library.prototype.findBookByTitle = function(title) {
return this.books.find(book => book.title === title) || null;
};

// Create a library and add books
const cityLibrary = new Library("City Public Library");

const book1 = new Book("JavaScript: The Good Parts", "Douglas Crockford", 176, "Programming");
const book2 = new Book("Eloquent JavaScript", "Marijn Haverbeke", 472, "Programming");
const book3 = new Book("Clean Code", "Robert C. Martin", 464, "Programming");

cityLibrary.addBook(book1);
cityLibrary.addBook(book2);
cityLibrary.addBook(book3);

// Use the library system
console.log(cityLibrary.books.length); // Output: 3

const foundBook = cityLibrary.findBookByTitle("Eloquent JavaScript");
console.log(foundBook.author); // Output: "Marijn Haverbeke"

console.log(foundBook.checkout()); // Output: "Eloquent JavaScript has been checked out."
console.log(foundBook.checkout()); // Output: "Eloquent JavaScript is not available for checkout."
console.log(foundBook.returnBook()); // Output: "Eloquent JavaScript has been returned."

This example shows how constructors help us create complex systems with multiple related object types, each with its own properties and behaviors.

Common Pitfalls and Best Practices

Forgetting to use the new keyword

If you forget to use the new keyword when calling a constructor function, this will point to the global object (or undefined in strict mode), leading to unexpected behavior:

javascript
function Person(name) {
this.name = name;
}

// Correct way:
const person1 = new Person("John");
console.log(person1.name); // "John"

// Incorrect way (without 'new'):
const person2 = Person("Jane"); // 'this' points to global object
console.log(person2); // undefined
console.log(window.name); // "Jane" (in browsers, 'name' is added to the window object)

Using ES6 Classes Instead

In modern JavaScript, ES6 classes provide a more elegant syntax for creating constructor-based objects:

javascript
class Person {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

getFullName() {
return `${this.firstName} ${this.lastName}`;
}
}

const person1 = new Person("John", "Doe", 30);
console.log(person1.getFullName()); // "John Doe"

Under the hood, ES6 classes still use the prototype system, but with cleaner syntax.

Summary

JavaScript object constructors provide a powerful way to create multiple objects with shared properties and methods. By using constructor functions with the new keyword, you can:

  1. Create a blueprint for objects with similar characteristics
  2. Assign unique property values to each instance
  3. Share methods efficiently using the prototype system
  4. Build complex systems with related object types

While newer JavaScript features like ES6 classes offer more modern syntax, understanding object constructors is fundamental to mastering JavaScript's object-oriented programming capabilities.

Exercises

To solidify your understanding of object constructors, try these exercises:

  1. Create a Circle constructor that takes a radius parameter and has methods to calculate area and circumference.
  2. Build a Todo constructor for a todo list app with methods to mark items complete or incomplete.
  3. Create a BankAccount constructor with methods for deposit, withdrawal, and checking balances.
  4. Extend the library example by adding a User constructor and methods for users to borrow and return books.

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)