12

次のような単純な ES6 クラスがあります。

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

new Ring(1, 2, 3)[3]Ring オブジェクトのインデックスがラップして、 1 が返され、3 が返されるようにしたいと考えていますnew Ring(1, 2, 3)[-1]。これはES6で可能ですか?もしそうなら、どのように実装しますか?

完全にカスタマイズされたゲッターを許可するプロキシについて読んだことがありますが、プロキシをクラスに適用する方法がわかりません。私はこれを管理しました:

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ラッピング インデックスをサポートする Ring オブジェクトになりました。問題は、毎回そのように Ring オブジェクトを定義しなければならないことです。new Ring()呼び出しがそれを返すように、このプロキシをクラスに適用する方法はありますか?

4

3 に答える 3

7

基本的には

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;
  }
}
于 2016-10-01T03:19:10.933 に答える
3

警告:これは醜いハックです

考えてみれば、これはかなり単純なアプローチです。

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

これにより関数が定義されましたClassToProxy。最初の引数は振る舞いを追加したいクラスで、2 番目の引数はハンドラーです。


使用例は次のとおりです。

const Ring = ClassToProxy(

    // Class
    class Ring {
        constructor(...items) {
            this.items = items;
        }
    },

    // Handler
    {
        get: function(target, name) {
            return target.items[name];
        }
    }
)
于 2016-10-01T02:34:37.100 に答える
0

基本的に次の 2 つの選択肢があります。

  • Proxy各インスタンスをラップする

    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);
        }
        …
    }
    
  • Proxyクラスのプロトタイプをラップします

    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];
        }
    });
    
于 2016-10-01T10:20:40.710 に答える