Skip to main content

Class Inheritance

Classes: Class Inheritance


What is the “extends” keyword used in JavaScript classes?

View Answer:
Interview Response: The extends keyword is used in class declarations or class expressions to create a class of a child of another class. We can use the "extends" keyword for subclassing bespoke classes and built-in objects such as the Date object and methods that return a class.

Code Example:

Syntax: class ChildClass extends ParentClass {...}

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

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

class Dog extends Animal {
constructor(name) {
super(name); // call the super class constructor and pass in the name parameter
}

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

let d = new Dog('Mitzie');

d.speak(); // Mitzie barks.

Can you use an expression after the extends keyword in JavaScript?

View Answer:
Interview Response: Yes, we can use an expression after the extends keyword. We can use the extends keyword to subclass custom classes and built-in objects such as the Date object and procedures meant to yield a class.

Code Example:

function f(phrase) {
return class {
sayHi() {
alert(phrase);
}
};
}

class User extends f('Hello') {}

new User().sayHi(); // Hello

In JavaScript, is it possible to override a method in a subclass?

View Answer:
Interview Response: Yes, we can override a method in a subclass by calling super on the method inside the method we want to override. This approach gives us access to the parent method, but we can still apply additional methods in conjunction with the `super.method` syntax.

Code Example:

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

run(speed) {
this.speed = speed;
alert(`${this.name} runs with speed ${this.speed}.`);
}

stop() {
this.speed = 0;
alert(`${this.name} stands still.`);
}
}

class Rabbit extends Animal {
hide() {
alert(`${this.name} hides!`);
}

stop() {
super.stop(); // call parent stop method
this.hide(); // and then the hide method
}
}

let rabbit = new Rabbit('White Rabbit');

rabbit.run(5); // White Rabbit runs with speed 5.
rabbit.stop(); // White Rabbit stands still. White Rabbit hides!

How does super behave inside of arrow functions JavaScript?

View Answer:
Interview Response: Arrow functions have no super; if it is accessed, it gets taken from the outer function context.

Code Example:

class Animal {
constructor() {
// ...
}
stop() {
console.log('stop what you are doing with super');
}
}
class Rabbit extends Animal {
stop() {
setTimeout(() => super.stop(), 1000); // called from the parent stop after 1 sec
}
}

let rabbit = new Rabbit();

rabbit.stop();

setTimeout(() => {
super.stop();
}, 1000);
// Syntax Error: 'super' outside of function or class

What happens if a class extends another class without an explicit constructor in the child class?

View Answer:
Interview Response: According to the specification, if a class extends another class and has no constructor, then the parent class constructor is generated in the child class, passing the child all the arguments in the parent. This behavior happens if we do not write a constructor of our own.

Code Example:

class Rabbit extends Animal {
// generated for extending classes without their own constructors
constructor(...args) {
super(...args);
}
}

How do you override a parent constructor in an inheriting class?

View Answer:
Interview Response: Inheriting classes must call super in their constructor before using this, or it results in an error. We use the super keyword to access and call functions on an object's parent. When used in a constructor, the super keyword appears alone, and we must use it before this keyword. The super keyword gets used to call functions on a parent object.

Code Example:

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

// ...
}

class Rabbit extends Animal {
constructor(name, earLength) {
super(name);
this.earLength = earLength;
}
// ...
}

// now fine
let rabbit = new Rabbit('White Rabbit', 10);
alert(rabbit.name); // White Rabbit
alert(rabbit.earLength); // 10

In JavaScript, is there a way to override class fields in parent classes?

View Answer:
Interview Response: We can override not only methods but also class fields. The main thing to remember is that the parent constructor always uses its field value, not the overridden one. To fix issues with overriding class fields, we can create a method to display the information needed in the inheriting class.

Code Example:

class Animal {
showName() {
// instead of this.name = 'animal'
console.log('animal');
}

constructor() {
this.showName(); // instead of console.log(this.name);
}
}

class Rabbit extends Animal {
showName() {
console.log('rabbit');
}
}

new Animal(); // animal
new Rabbit(); // rabbit

Can you explain how super works under the hood as [[HomeObject]]?

View Answer:
Interview Response: While one might expect Obj.method() to reach up and call into Obj.prototype.method, this is not the case. To find super.method(), the called function uses its home object, a value created when it was initially defined and one that does not get changed when the method gets reassigned. When a function gets specified as a class or object method, its [[HomeObject]] property becomes that object. Then super uses it to resolve the parent prototype and its methods.

Code Example:

let animal = {
name: 'Animal',
eat() {
// animal.eat.[[HomeObject]] == animal
alert(`${this.name} eats.`);
},
};

let rabbit = {
__proto__: animal,
name: 'Rabbit',
eat() {
// rabbit.eat.[[HomeObject]] == rabbit
super.eat();
},
};

let longEar = {
__proto__: rabbit,
name: 'Long Ear',
eat() {
// longEar.eat.[[HomeObject]] == longEar
super.eat();
},
};

// works correctly
longEar.eat(); // Long Ear eats.
note

You should never call proto in your code… In this case, just call super.