JavaScript > Prototypes and Inheritance > Constructor Functions and Classes > Constructor functions

Constructor Functions in JavaScript

This snippet demonstrates how to create objects using constructor functions in JavaScript, including adding properties and methods to objects created from the constructor and exploring the prototype chain.

Basic Constructor Function

This code defines a constructor function named `Person`. It takes `firstName`, `lastName`, and `age` as arguments and assigns them as properties to the newly created object using the `this` keyword. A method `getFullName` is also added directly to each object instance. The `new` keyword is crucial; it creates a new object, sets its prototype to `Person.prototype`, executes the constructor function with `this` bound to the new object, and returns the new object. Without `new`, the function call would not create a new object and `this` would refer to the global object (window in browsers, global in Node.js), potentially causing unintended side effects.

// Define a constructor function
function Person(firstName, lastName, age) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
  this.getFullName = function() {
    return this.firstName + ' ' + this.lastName;
  };
}

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

console.log(person1.firstName); // Output: John
console.log(person2.getFullName()); // Output: Jane Smith

Adding Methods to the Prototype

This code demonstrates adding a method (`makeSound`) to the `Animal.prototype`. This is more efficient than defining the method directly within the constructor function because the method is only defined once on the prototype and shared by all instances of `Animal`. Each `Animal` object inherits the `makeSound` method from `Animal.prototype`. This is a core principle of prototypal inheritance in JavaScript.

// Define a constructor function
function Animal(name, species) {
  this.name = name;
  this.species = species;
}

// Add a method to the prototype
Animal.prototype.makeSound = function() {
  console.log('Generic animal sound');
};

// Create objects
const animal1 = new Animal('Leo', 'Lion');
const animal2 = new Animal('Tweety', 'Bird');

animal1.makeSound(); // Output: Generic animal sound
animal2.makeSound(); // Output: Generic animal sound

Concepts behind the snippet

Constructor Functions: Constructor functions are special functions used to create and initialize objects. They are typically invoked using the new keyword.

Prototypes: Every function in JavaScript has a prototype property, which is an object. When a constructor function is used to create objects with the new keyword, the newly created object inherits properties and methods from the constructor's prototype. This is the basis of prototypal inheritance.

Prototypal Inheritance: JavaScript uses prototypal inheritance. Objects inherit properties and methods from their prototype. The prototype itself can also inherit from another prototype, creating a prototype chain.

Real-Life Use Case

Consider a scenario where you're building a game. You might have a `Character` constructor function. Instead of defining methods like `move`, `attack`, and `defend` directly on each character object, you can define them on `Character.prototype`. This significantly reduces memory usage, especially when dealing with hundreds or thousands of characters in the game.

Best Practices

  • Use PascalCase for Constructor Functions: It's a convention to use PascalCase (e.g., Person, Animal) for constructor functions to distinguish them from regular functions.
  • Add Methods to the Prototype: For efficiency, add methods to the constructor's prototype rather than defining them within the constructor function itself.
  • Avoid Modifying Built-in Prototypes: While it's possible to add properties or methods to built-in prototypes like Array.prototype or String.prototype, it's generally discouraged as it can lead to naming conflicts and unexpected behavior.

Interview Tip

Be prepared to explain the difference between defining a method directly on an object instance versus adding it to the constructor's prototype. Understand how the new keyword works and how it affects the this context within the constructor function. Explain the concept of the prototype chain.

When to use them

Use constructor functions when you need to create multiple objects with similar properties and methods. They provide a structured way to initialize objects and manage their behavior through prototypal inheritance. They are very suitable to create classes.

Memory footprint

Defining methods on the prototype reduces memory consumption. If methods are defined inside the constructor function, each object instance gets its own copy of the method, leading to higher memory usage. Methods on the prototype are shared by all instances.

Alternatives

  • Classes (ES6): ES6 introduced the class syntax, which provides a more structured and familiar (to developers coming from class-based languages) way to create objects and manage inheritance. However, classes in JavaScript are still based on prototypal inheritance under the hood.
  • Factory Functions: Factory functions are another way to create objects. They are regular functions that return new objects. They don't require the new keyword.

Pros

  • Prototypal Inheritance: Offers a flexible inheritance model.
  • Memory Efficiency: Methods defined on the prototype are shared among all instances.
  • Familiar Pattern: A well-established pattern in JavaScript.

Cons

  • Complexity: Can be more complex to understand than class-based inheritance, especially for developers new to JavaScript.
  • Less Readable (Compared to Classes): The syntax can be less readable compared to the class syntax introduced in ES6.

FAQ

  • What is the purpose of the 'new' keyword when using constructor functions?

    The new keyword performs several crucial actions: 1. Creates a new empty object. 2. Sets the prototype of the new object to the constructor function's prototype (ConstructorFunction.prototype). 3. Binds the this keyword within the constructor function to the newly created object. 4. Returns the new object (unless the constructor explicitly returns a different object).
  • How do I add a method to all objects created by a specific constructor function?

    Add the method to the constructor function's prototype property. For example: MyConstructor.prototype.myMethod = function() { /* method logic */ };
  • What happens if I forget to use the 'new' keyword when calling a constructor function?

    If you forget to use the new keyword, the this keyword within the constructor function will refer to the global object (window in browsers, global in Node.js). This can lead to unintended side effects, such as polluting the global scope with properties and methods. The function will not return a new object.