I am trying to create a subclass of javascript's Array. I want to initiate subclass with array-type argument and add a method to remove an element from the array (subclass).
My code looks like this:
class CustomArray extends Array {
constructor(array) {
console.log('Initiating array:', array)
super(...array);
}
remove(element) {
let index = this.indexOf(element);
if (index > -1) {
return this.splice(index, 1);
}
return [];
}
}
var a = ['a', 'b', 'c', 'd', 'e'];
var list = new CustomArray(a)
console.log('list:', list);
console.log('remove:', list.remove('c'));
console.log('list:', list);
The problem is that when I call .splice() it removes element from array, but also returns array of deleted elements, actually it returns new instance of my subclass CustomArray, which should be initiated with argument of array type, but .splice() initiates it with arguments of integer type.
Here is an example of what I think happens when I call .splice():
Let's say we have instance list
of CustomArray
class initiated with argument ['a','b','c','d','e']
and then we call method list.remove('c')
. (Just like in code snippet).
Method remove
of CustomArray
class checks the index of c
is in array ['a','b','c','d','e']
, which is 2
and then calls method this.splice(2,1)
which should remove 1 element at index 2 in array ['a','b','c','d','e']
. Method splice
removes element c
form array, but also returns something like new CustomArray(1)
because one element was removed form array so it tries to create array of length 1, but that failes because class CustomArray
is expectiong array.
I want to prevent splice
method from initiating a new instance of CustomArray
class and instead return normal array (an instance of Array object).
I want to prevent
splice
method from initiating a new instance ofCustomArray
class and instead return normal array (an instance ofArray
object).
Then you need to create a different method with a different name. The semantics of splice
are clearly and precisely defined; they form a contract for the Array
type. Having your CustomArray
violate that contract would mean it isn't an Array
anymore, it's something array-like, and shouldn't extend Array
.
Since your method is called remove
, that's fine; if you want remove
to return Array
, not CustomArray
, you just need to implement the logic yourself:
remove(element) {
let index = this.indexOf(element);
if (index > -1) {
const newLength = this.length - 1;
while (index < newLength) {
this[index] = this[index + 1];
++index;
}
this.length = newLength;
return [element];
}
return [];
}
Alternately, of course, make CustomArray
's constructor work correctly when called by the various Array.prototype
methods. (The one you have in the question works just fine, other than logging something you don't expect with console.log
.)