Search code examples
javascriptecmascript-6es6-classes6-proxy

Custom Array-like getter in JavaScript


I have a simple ES6 class, like so:

class Ring extends Array {
    insert (item, index) {
        this.splice(index, 0, item);
        return this;
    }
}

I want to make it so that the indexing for Ring objects wraps, so that new Ring(1, 2, 3)[3] returns 1, new Ring(1, 2, 3)[-1] returns 3, and so on. Is this possible in ES6? If so, how would I implement it?

I've read about proxies, which allow a completely customized getter, but I can't figure out how to apply a proxy to a class. I did manage this:

var myRing = new Proxy (Ring.prototype, {
    get: function (target, name) {
        var len = target.length;
        if (/^-?\d+$/.test(name))
            return target[(name % len + len) % len];
        return target[name];
    }
});

myRing is now a Ring object that supports wrapping indices. The problem is that I'd have to define Ring objects like that every time. Is there a way to apply this proxy to the class such that calling new Ring() returns it?


Solution

  • Basically it is

    class ProxyRing extends Array {
      constructor(...args) {
        super(...args)
    
        return new Proxy(this, {
          get: function (target, name) {
              var len = target.length;
              if (typeof name === 'string' && /^-?\d+$/.test(name))
                  return target[(name % len + len) % len];
              return target[name];
          }
        });
      }
    
      insert (item, index) {
          this.splice(index, 0, item);
          return this;
      }
    }