0

非常によく似たタスクを実行する必要がある小さなオブジェクトがたくさんあり、デコレータを使用してこれらのオブジェクトを変更したいと考えています。これにより、物事がずっと簡単になります。問題は、これらのオブジェクトの特定のデータにアクセスするとすぐにトリガーする必要があると同時に、実際のデータへの外部アクセスを防止する必要があることです。したがって、クロージャーを使用してプライベート データを保存し、外部アクセス用の魔法のミューテーターを提供しています。最後に、特に理由もなくコンストラクターも使用しています。

これは、オブジェクトと頭の痛い部分の非常に縮小されたバージョンです。

var Foo = function () {
  var hiddenState;
  return {
    set state (s) {
      // Do something that justifies using magical accessors
      state = s;
    },
    get state () {
      // Do something that justifies using magical accessors
      return state;
    }
  }
};

var o = new Foo();
o.state = 10;

さて、ミューテーターが使用されたときに残りのオブジェクトとは異なる動作をする必要があるオブジェクトがいくつかあります。だから、ミューテーターを上書きするだけでいいと思いました。

// Let's suppose I have some reason to modify the magical accessors for some objects but not for others
Object.defineProperty(o, 'state', {
  get: function () {return hiddenState /*...*/},
  set: function (s) {state = s /*...*/}
});

o.state; // Ouch!

これはうまくいきません。hiddenState新しい getter/setter ペアのスコープ内で定義されていないときにアクセスしようとすると、参照エラーが発生します。

新しいミューテーターを渡すとすぐに、古いミューテーターからしかアクセスできなかったクロージャーを JS がダンプするのではないかと思います。この問題に対処する方法はありますか?

4

1 に答える 1

1

hiddenStateを使用してアクセスできるクロージャーにアクセスできますObject.getOwnPropertyDescriptor。また、ゲッターを変更する必要がない場合は、まったく上書きしないでください。永続化されます。

var oldSetter = Object.getOwnPropertyDescriptor(o, 'state').set;
Object.defineProperty(o, 'state', {
  set: function (s) {
    /* do something to s */
    oldSetter(s);
  }
});
于 2015-11-04T17:40:36.350 に答える