Extending built-in classes
Classes: Extending Natives
When extending built-in classes, what is used in their internal implementation to extend the built-in class?
View Answer:
Interview Response: Built-in methods like an array, filter, map, and others return new objects of the inherited type. Their internal implementation uses the object’s constructor property for that. If you test the strict equality between the newly created object and child class on the constructor, it returns true.
Code Example:
class PowerArray extends Array {
isEmpty() {
return this.length === 0;
}
}
let arr = new PowerArray(1, 2, 5, 10, 50);
// Strict Equality Test
console.log(arr.constructor === PowerArray); // returns true
Can you explain the function and syntax of the Symbol.species accessor property?
View Answer:
Interview Response: Subclasses can override the default constructor for objects using the species accessor attribute. When we wish to retrieve Array instances in our derived array class, we utilize Symbol.species. When utilizing methods that return the default constructor, such as map(), we may wish these methods to return a parent Array object rather than the extending object.
Technical Response: The symbol Symbol.species specifies a function-valued property that the constructor function uses to create derived objects. Subclasses can override the default constructor for objects using the species accessor attribute. Symbol.species gets used when you may want to return Array objects in your derived array class. When utilizing methods that return the default constructor, such as map(), you want these methods to return a parent Array object rather than the extending object.
Code Example:
Syntax: [Symbol.species]() { return Array; }
Syntax: [Symbol.species]() { return Array; }
class MyArray extends Array {
// Overwrite species to the parent Array constructor
static get [Symbol.species]() {
return Array;
}
}
let a = new MyArray(1, 2, 3);
let mapped = a.map((x) => x * x); We are using map to return the object constructor
console.log(mapped instanceof MyArray); // false
console.log(mapped instanceof Array); // true
console.log(mapped[1]); // returns value at index 1 times 2 - value = 4
console.log(a); // returns Array - [ 1, 2, 3 ]
note
To guarantee that you are accessing the correct array, maintain track of the supplied object (Array). If the method returns a new array like the filter() method, it may unexpectedly negatively affect your application when used in conjunction with the species Symbol. There are benefits to this behavior that allow us to customize specific interactions within the inheriting class.
How does static inheritance work between native built-in classes?
View Answer:
Interview Response: Normally, static and non-static methods are inherited when one class extends another. But built-in classes are an exception, and they do not inherit statics from each other.
Example: Both Array and Date inherit from Object, so their instances have methods from Object.prototype. But Array.[[Prototype]] does not reference Object, so there’s no, for instance, Array.keys() (or Date.keys()) static method.