Interview

10 OOP in JavaScript Interview Questions and Answers

Prepare for your next interview with this guide on OOP in JavaScript, featuring common questions and answers to enhance your coding skills.

Object-Oriented Programming (OOP) in JavaScript is a fundamental concept that underpins many modern web development practices. By leveraging OOP principles, developers can create more modular, reusable, and maintainable code. JavaScript’s flexibility allows for the implementation of OOP concepts such as inheritance, encapsulation, and polymorphism, making it a powerful tool for building complex applications.

This article provides a curated selection of interview questions focused on OOP in JavaScript. Reviewing these questions will help you deepen your understanding of OOP principles and demonstrate your proficiency in applying them within JavaScript, thereby enhancing your readiness for technical interviews.

OOP in JavaScript Interview Questions and Answers

1. Write a class in JavaScript that represents a Car with properties for make, model, and year. Include a method to display this information.

In JavaScript, a class can be defined using the class keyword. The class can have a constructor to initialize its properties and methods to perform actions. Here is an example of a Car class with properties for make, model, and year, and a method to display this information:

class Car {
    constructor(make, model, year) {
        this.make = make;
        this.model = model;
        this.year = year;
    }

    displayInfo() {
        return `${this.year} ${this.make} ${this.model}`;
    }
}

const myCar = new Car('Toyota', 'Corolla', 2020);
console.log(myCar.displayInfo()); // Output: 2020 Toyota Corolla

2. What is inheritance and how is it implemented? Provide an example.

Inheritance allows a class to inherit properties and methods from another class. This is achieved using the extends keyword. The child class can also override or extend the functionality of the parent class.

Example:

class Animal {
    constructor(name) {
        this.name = name;
    }

    speak() {
        console.log(`${this.name} makes a noise.`);
    }
}

class Dog extends Animal {
    constructor(name, breed) {
        super(name);
        this.breed = breed;
    }

    speak() {
        console.log(`${this.name} barks.`);
    }
}

const dog = new Dog('Rex', 'German Shepherd');
dog.speak(); // Rex barks.

In this example, the Dog class inherits from the Animal class. The Dog class uses the super keyword to call the constructor of the Animal class, ensuring that the name property is properly initialized. The speak method in the Dog class overrides the speak method in the Animal class.

3. Describe polymorphism and provide a code example demonstrating it.

Polymorphism allows methods to do different things based on the object it is acting upon. This is typically achieved through method overriding, where a subclass provides a specific implementation of a method that is already defined in its superclass.

Example:

class Animal {
    speak() {
        console.log("The animal makes a sound");
    }
}

class Dog extends Animal {
    speak() {
        console.log("The dog barks");
    }
}

class Cat extends Animal {
    speak() {
        console.log("The cat meows");
    }
}

function makeAnimalSpeak(animal) {
    animal.speak();
}

const myDog = new Dog();
const myCat = new Cat();

makeAnimalSpeak(myDog); // The dog barks
makeAnimalSpeak(myCat); // The cat meows

4. How does encapsulation work? Illustrate with an example.

Encapsulation is the practice of bundling data and methods that operate on the data into a single unit, typically a class. It also involves restricting access to some of the object’s components, which can be done using private fields and methods. This ensures that the internal representation of the object is hidden from the outside, only exposing a controlled interface.

Example using ES6 classes and private fields:

class Person {
    #name; // private field

    constructor(name) {
        this.#name = name;
    }

    getName() {
        return this.#name;
    }

    setName(newName) {
        if (typeof newName === 'string' && newName.length > 0) {
            this.#name = newName;
        } else {
            console.log('Invalid name');
        }
    }
}

const person = new Person('John');
console.log(person.getName()); // John
person.setName('Doe');
console.log(person.getName()); // Doe
console.log(person.#name); // SyntaxError: Private field '#name' must be declared in an enclosing class

In this example, the #name field is private and cannot be accessed directly from outside the class. The getName and setName methods provide controlled access to the private field.

5. Write a class Animal and extend it to create a subclass Dog. Add a method to each class and demonstrate calling these methods.

In JavaScript, classes are a template for creating objects. The extends keyword is used to create a subclass, which inherits methods and properties from a parent class.

class Animal {
    constructor(name) {
        this.name = name;
    }

    speak() {
        console.log(`${this.name} makes a noise.`);
    }
}

class Dog extends Animal {
    constructor(name, breed) {
        super(name);
        this.breed = breed;
    }

    speak() {
        console.log(`${this.name} barks.`);
    }
}

const animal = new Animal('Generic Animal');
animal.speak(); // Generic Animal makes a noise.

const dog = new Dog('Rex', 'German Shepherd');
dog.speak(); // Rex barks.

6. What are getters and setters? Write a class that uses both.

Getters and setters are used to control access to an object’s properties. A getter method allows you to define a method that will be executed when a property is accessed, while a setter method allows you to define a method that will be executed when a property is set. This provides a way to add logic to the process of getting or setting a property value.

Here is an example of a JavaScript class that uses both getters and setters:

class Person {
    constructor(name, age) {
        this._name = name;
        this._age = age;
    }

    // Getter for name
    get name() {
        return this._name;
    }

    // Setter for name
    set name(newName) {
        if (typeof newName === 'string' && newName.length > 0) {
            this._name = newName;
        } else {
            console.error('Invalid name');
        }
    }

    // Getter for age
    get age() {
        return this._age;
    }

    // Setter for age
    set age(newAge) {
        if (typeof newAge === 'number' && newAge > 0) {
            this._age = newAge;
        } else {
            console.error('Invalid age');
        }
    }
}

const person = new Person('John', 30);
console.log(person.name); // John
person.name = 'Doe';
console.log(person.name); // Doe
person.age = 25;
console.log(person.age); // 25

7. Discuss the role of the super keyword. Provide an example.

The super keyword allows a child class to call and access properties and methods of its parent class. When a child class extends a parent class, the super keyword can be used to call the parent’s constructor and methods, ensuring that the parent class is properly initialized and its functionality is available to the child class.

Example:

class Animal {
    constructor(name) {
        this.name = name;
    }

    speak() {
        console.log(`${this.name} makes a noise.`);
    }
}

class Dog extends Animal {
    constructor(name, breed) {
        super(name);
        this.breed = breed;
    }

    speak() {
        super.speak();
        console.log(`${this.name} barks.`);
    }
}

const dog = new Dog('Rex', 'German Shepherd');
dog.speak();

In this example, the Dog class extends the Animal class. The super keyword is used in the Dog constructor to call the Animal constructor, ensuring that the name property is properly initialized. Additionally, the super.speak() call in the Dog class’s speak method allows the Dog class to reuse the speak method from the Animal class before adding its own behavior.

8. Explain method overriding with an example.

Method overriding occurs when a subclass provides a specific implementation of a method that is already defined in its superclass. This allows the subclass to modify or extend the behavior of the inherited method. It is a key feature for achieving polymorphism in object-oriented programming.

Example:

class Animal {
    speak() {
        console.log("The animal makes a sound");
    }
}

class Dog extends Animal {
    speak() {
        console.log("The dog barks");
    }
}

let myDog = new Dog();
myDog.speak(); // Output: The dog barks

In this example, the Dog class overrides the speak method of the Animal class. When the speak method is called on an instance of Dog, the overridden method in the Dog class is executed, demonstrating how method overriding allows for specific behavior in subclasses.

9. What are static methods and properties? Provide an example.

Static methods and properties are defined using the static keyword. They are called on the class itself, not on instances of the class. This means you can use them without creating an instance of the class. Static methods are typically used for utility functions, such as functions that perform operations on data that is passed to them as arguments.

Example:

class MathUtils {
    static add(a, b) {
        return a + b;
    }

    static get description() {
        return 'This class provides basic math utilities.';
    }
}

console.log(MathUtils.add(5, 3)); // 8
console.log(MathUtils.description); // This class provides basic math utilities.

In this example, add is a static method and description is a static property. They can be accessed directly on the MathUtils class without creating an instance of the class.

10. Describe object composition and how it differs from inheritance. Provide an example.

Object composition is a design principle where objects are composed using other objects, rather than inheriting from a parent class. This approach allows for greater flexibility and reusability, as it avoids the pitfalls of a rigid class hierarchy.

Example of inheritance:

class Animal {
    constructor(name) {
        this.name = name;
    }

    speak() {
        console.log(`${this.name} makes a noise.`);
    }
}

class Dog extends Animal {
    speak() {
        console.log(`${this.name} barks.`);
    }
}

const dog = new Dog('Rex');
dog.speak(); // Rex barks.

Example of object composition:

const canSpeak = (state) => ({
    speak: () => console.log(`${state.name} makes a noise.`)
});

const canBark = (state) => ({
    bark: () => console.log(`${state.name} barks.`)
});

const createDog = (name) => {
    const state = { name };
    return Object.assign({}, canSpeak(state), canBark(state));
};

const dog = createDog('Rex');
dog.speak(); // Rex makes a noise.
dog.bark();  // Rex barks.
Previous

10 ER Diagram Interview Questions and Answers

Back to Interview
Next

10 DNS server Interview Questions and Answers