0

I'm using the myarray.length = 0 method to truncate an array via a custom Array.prototype.clear() method.

This has worked so far to my knowledge, but I now have a particular case where it's setting the length to 0, but the elements still remain.

I've run a basic Array test and it seems to work, but in this more complex case, it is not, so it's hard to diagnose the problem.

Here is the extension code on my Array.prototype that I have used...

Object.defineProperty(Array.prototype, 'clear', {
    value: function clear() {
        // Clear the array using the length = 0 method. See the method's comments on links to more information and benchmarks on this technique.
        this.length = 0;
    },
    enumerable: false,
    configurable: true,
    writable: false
});

When I call it on all other cases, the following works brilliantly.

var myarray = [ 1,2,3,4,5,6,6,7,8,9, new Date() ];
myarray.clear();
console.log(myarray);   // all cleared.  { length: 0 }

But in my more complex case where the array has about 10-20 elements and I call the .clear() on the array, it sets the length to 0 but the elements can still be seen if I console.log the array like I did above.

// e.g. { 0: ..., 1: ..., 2: ..., 3: ..., 4: ..., length: 0 }

The only difference is that the Array object I am using is an extended object, with an override, which does call the overridden function. something like so...

function Collection() { Array.apply(this); }
Collection.prototype = Object.create(Array.prototype, {
    push: {
        enumerable: false,
        value: function(item) { 
            // ...does a type checks on 'item'
            Array.prototype.push.apply(this, [ item ]);
        }
    },
    clear: {
        enumerable: false,
        value: function() { Array.prototype.clear.apply(this); }
    }
});

This is happening in Chrome, and I have stepped it thru to the Array.prototype.clear method, just as my testing did, but for some reason it does not work in the second case.

Any ideas?

5
  • 3
    Seems like you're trying it on an object, and on an object length would just be another property, and wouldn't change the contents of the object. Note that it's generally a bad idea to extend native prototypes Commented Sep 29, 2017 at 4:45
  • I wouldn't say it's a bad idea to extend natives ... with the exception of Array - it has "magic powers" compared to other natives Commented Sep 29, 2017 at 4:47
  • @JaromandaX - it's not always a bad idea, but it's generally a bad idea, meaning I think it should be avoided, for instance in this case, where a regular clear(Array) would do the same thing, without touching the prototype. At least it's not enumerable. Commented Sep 29, 2017 at 4:48
  • agreed, @adeneo I misunderstood - I was thinking of his class extension Commented Sep 29, 2017 at 4:49
  • Thanks, but ended up changing it to Array.prototype.splice() until I find something better. @adeneo, this project is massive, so trying to keep things object'ified where possible. Your idea about it being treated as an object; never considered it, as I was calling the Array's prototype function. But interesting to know. Commented Sep 29, 2017 at 10:18

1 Answer 1

2

if you use new ES2015+ class

    Object.defineProperty(Array.prototype, 'clear', {
        value: function clear() {
            this.length = 0;
        },
        enumerable: false,
        configurable: true,
        writable: false
    });

    class Collection extends Array {
        constructor(...args) {
            super(...args);
        }
        push(...args) {
            console.log('overridden push', ...args);
            // only push even values for example
            super.push(...args.filter(x=>x%2 == 0));
        }
    }

    var x = new Collection();
    x.push(1,2,3,4);
    console.log('after push', JSON.stringify(x));
    x.clear();
    console.log('after clear', JSON.stringify(x));

or you can avoid adding clear to array

    class Collection extends Array {
        constructor(...args) {
            super(...args);
        }
        push(...args) {
            console.log('overridden push', ...args);
            // only push even values for example
            super.push(...args.filter(x=>x%2 == 0));
        }
        clear() {
            this.length = 0;
        }
    }

    var x = new Collection();
    x.push(1,2,3,4);
    console.log('after push', JSON.stringify(x));
    x.clear();
    console.log('after clear', JSON.stringify(x));

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @JaromandaX. I like the ES2015+ and would love to use it...alas browser (backward) support just still isn't fully there yet sigh. I wonder if it has something to do with it being an Object, as @adeneo mentioned. Have resulted in using the Array.prototype.splice() method, which seems to do the trick.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.