Extending built-in classes
Classes: Extending Natives
What is a native built-in class in JavaScript?
View Answer:
What does it mean to extend a native built-in class?
View Answer:
class MyArray extends Array {
get first() {
return this[0];
}
get last() {
return this[this.length - 1];
}
}
let myArr = new MyArray();
myArr.push(1, 2, 3, 4, 5);
console.log(myArr.first); // Output: 1
console.log(myArr.last); // Output: 5
How do you extend a built-in class in JavaScript?
View Answer:
class MyArray extends Array {
// Custom methods and properties
}
Can you provide an example of a custom method added to a built-in class?
View Answer:
class MyString extends String {
reverse() {
return this.split('').reverse().join('');
}
Are there any limitations when extending built-in classes?
View Answer:
class MyArray {
constructor() {
this.array = []; // using array literal
}
push(value) {
this.array.push(value);
}
pop() {
return this.array.pop();
}
get first() {
return this.array[0];
}
get last() {
return this.array[this.array.length - 1];
}
// ... any other methods you want to expose
}
let myArr = new MyArray();
myArr.push(1);
myArr.push(2);
myArr.push(3);
myArr.push(4);
myArr.push(5);
console.log(myArr.first); // Output: 1
console.log(myArr.last); // Output: 5
In this example, we're defining a new class MyArray
that mimics some of the functionality of the Array
class (push
and pop
methods), but also adds custom properties first
and last
. Note that MyArray
is not a subclass of Array
, but rather uses an Array
instance internally (this.array
). This can often be a safer and more flexible approach than subclassing built-in classes directly.
When should you extend built-in classes?
View Answer:
Can you provide an example of when it's better to use a utility function instead of extending a built-in class?
View Answer:
function sum(array) {
return array.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
}
const result = sum([1, 2, 3, 4]); // 10
Can you explain the internal constructor implementation when extending built-in classes in JavaScript?
View Answer:
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 of the Symbol.species accessor property?
View Answer:
Syntax: [Symbol.species]() { return Array; }
class MyArray extends Array {
// Overwrite species to the parent Array constructor
static get [Symbol.species]() {
return Array;
}
sum() {
return this.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
}
}
const myArrayInstance = new MyArray(1, 2, 3, 4);
const sliced = myArrayInstance.slice(1, 3); // creates a new Array instance, not MyArray
console.log(sliced instanceof Array); // true
console.log(sliced instanceof MyArray); // false
In this example, the Symbol.species accessor property is used to ensure that the slice method returns a new instance of the built-in Array class, instead of a MyArray instance.
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:
class ExtendedArray extends Array {
static greet() {
console.log("Hello, World!");
}
}
// Calling static method from subclass
ExtendedArray.greet(); // Output: Hello, World!
// Built-in static method is not inherited, needs direct reference
console.log(ExtendedArray.isArray([])); // Output: Error
console.log(Array.isArray([])); // Output: True