Custom Array-like getter in JavaScript

后端 未结 3 1009
无人及你
无人及你 2021-02-14 05:28

I have a simple ES6 class, like so:

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


        
相关标签:
3条回答
  • 2021-02-14 05:59

    Warning: This is an ugly hack

    This is a rather simple approach when you think about it.

    function ClassToProxy(_class, handler) {
        return (...args) => new Proxy(new _class(...args), handler);
    }
    

    This defined a function ClassToProxy. The first argument is the class you want to add behavior too, and the second is the handler.


    Here's example usage:

    const Ring = ClassToProxy(
    
        // Class
        class Ring {
            constructor(...items) {
                this.items = items;
            }
        },
    
        // Handler
        {
            get: function(target, name) {
                return target.items[name];
            }
        }
    )
    
    0 讨论(0)
  • 2021-02-14 06:16

    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;
      }
    }
    
    0 讨论(0)
  • 2021-02-14 06:21

    You basically have two choices:

    • Wrap a Proxy around each instance

      const handler = {
          get(target, name) {
              var len = target.length;
              if (typeof name === 'string' && /^-?\d+$/.test(name))
                  return target[(name % len + len) % len];
              return target[name];
          }
      };
      class Ring extends Array {
          constructor() {
              super()
              return new Proxy(this, handler);
          }
          …
      }
      
    • wrap a Proxy around the prototype of your class

      class Ring extends Array {
          constructor() {
              super()
          }
          …
      }
      Ring.prototype = new Proxy(Ring.prototype, {
          get(target, name, receiver) {
              var len = target.length;
              if (typeof name === 'string' && /^-?\d+$/.test(name)) {
                  if (+name < 0)
                      return receiver[(name % len) + len];
                  if (+name > len-1)
                      return receiver[name % len];
              }
              return target[name];
          }
      });
      
    0 讨论(0)
提交回复
热议问题