2

I am trying to make a custom Array class by extending the native Array, but I can't figure out how to empty the elements, here's my try.

class MyArray extends Array {
  // for simplicity I just included the bit of code that fails.
  reset () {
    this = []; // fails of course
  }
}

const myarray = new MyArray();
myarray.push(1);
myarray.reset(); // fails because it tries to rewrite `this`

What am I doing wrong ?

vdegenne
  • 12,272
  • 14
  • 80
  • 106
  • 3
    set the length to zero `this.legnth = 0`? – evolutionxbox Jan 28 '21 at 17:28
  • 1
    @evolutionxbox I saw this solution on internet but I don't think it's a valid one because the elements will still be in the memory, won't they ? – vdegenne Jan 28 '21 at 17:31
  • I'm not actually sure. What makes you think that? – evolutionxbox Jan 28 '21 at 17:31
  • @evolutionxbox because `length` is mostly used as a getter and I don't think using it as a setter will trigger the internal process of Array to clear all the items. – vdegenne Jan 28 '21 at 17:34
  • Do you know how to validate that? – evolutionxbox Jan 28 '21 at 17:34
  • @evolutionxbox I do not. – vdegenne Jan 28 '21 at 17:38
  • Do you know where you may have read about it? – evolutionxbox Jan 28 '21 at 17:39
  • @evolutionxbox Yes you provided an answer with a quote that says it's a read/write property, but how does it prove the write implementation will clear all the items from the list ? – vdegenne Jan 28 '21 at 17:46
  • 1
    Implementations change all the time. I can only go by the language specification https://tc39.es/ecma262/#sec-arraysetlength – evolutionxbox Jan 28 '21 at 17:57
  • 1
    @vdegenne ... from MDN's [Shortening an array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length#shortening_an_array) to ECMA-262's [23.1.4.1 length](https://tc39.es/ecma262/#sec-properties-of-array-instances-length) – Peter Seliger Jan 28 '21 at 17:57
  • 3
    An easy test would be `ns = [1,2]` `ns.length = 0` `ns.length = 2` which results in an array with 2 empty slots. Meaning that the underlying references are cleared. – 3limin4t0r Jan 28 '21 at 17:59
  • @3limin4t0r that was clever. thanks – vdegenne Jan 28 '21 at 18:00
  • @3limin4t0r that's a great test. – evolutionxbox Jan 28 '21 at 18:00
  • @3limin4t0r ... The slots of your tiny example are in the end not just empty, they literally do not exist. It's an entirely *sparse* array. – Peter Seliger Jan 28 '21 at 20:32
  • @PeterSeliger Isn't that the definition of an empty slot? If I say that index 2 of array x is an empty slot, I don't mean that the value on that index is 2 is set to `undefined` or `null`. I mean that the array does not have the index 2. For example: `[1,null,,undefined,2]` here only index 2 is an empty slot. – 3limin4t0r Jan 28 '21 at 20:59
  • @3limin4t0r ... you are totally right. Please excuse my hastiness. I've got lost in terminology. And in addition I should have checked it before ... because the chrome console even logs it spec-conform ... like for `[,,,,,]` => `(5) [empty × 5]`. – Peter Seliger Jan 28 '21 at 21:16

2 Answers2

5

Setting the array length to zero will remove all elements.

class MyArray extends Array {
  // for simplicity I just included the bit of code that fails.
  reset () {
    this.length = 0;
  }
}

const myarray = new MyArray();
myarray.push(1,2,3,4);

console.log('before', myarray);
myarray.reset();
console.log('after', myarray);

See How do I empty an array in JavaScript? for more methods of emptying an array.

This method is mentioned in the accepted answer:

Method 2 (as suggested by Matthew Crumley)

A.length = 0

This will clear the existing array by setting its length to 0. Some have argued that this may not work in all implementations of JavaScript, but it turns out that this is not the case. It also works when using "strict mode" in ECMAScript 5 because the length property of an array is a read/write property.

evolutionxbox
  • 3,932
  • 6
  • 34
  • 51
2

You can use splice

class MyArray extends Array {
  // for simplicity I just included the bit of code that fails.
  reset () {
    this.splice(0, this.length);
  }
}

const myarray = new MyArray();
myarray.push(...[1,2,3,4]);

console.log('before', myarray);
myarray.reset();
console.log('after', myarray);
Zain Ul Abideen
  • 1,617
  • 1
  • 11
  • 25
  • I didn't downvote, and I think it's also a great solution. I will prefer `this.length = 0` though, probably for performance reasons. Thanks. – vdegenne Jan 28 '21 at 18:03
  • @vdegenne not complaining, but do tests with performance. Don’t pre-optimise – evolutionxbox Jan 28 '21 at 18:37
  • @evolutionxbox Your statement is legit, I usually test to support my assumptions. But here it's quite obvious that this solution is weaker in performance. Because you call `splice` and `length` which are already 2 functions and `splice` will create another variable to contain the data it returns, so you know it'll be more intensive. But if you really need a proof : https://jsbin.com/yepudas/edit?js,console – vdegenne Jan 29 '21 at 01:05
  • @evolutionxbox it was in response to your comment above. – vdegenne Jan 29 '21 at 01:09
  • OP and @evolutionxbox it is healthy discussion. In my opinion its trade off between two; memory and time. – Zain Ul Abideen Jan 29 '21 at 15:34