创建可以访问闭包的装饰器

Creating decorators with access to closures

我有很多小对象,它们都需要完成非常相似的任务,我想使用装饰器来修改这些对象,因为这让我的事情变得容易多了。问题是,我还需要在访问这些对象上的某些数据时立即触发内容,同时防止外部访问实际数据。因此,我使用闭包来存储私有数据并为外部访问提供神奇的修改器。最后,我还无缘无故地使用了构造函数。

这是一个非常简化的对象版本和让我头疼的部分:

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 就会转储只能从旧修改器访问的闭包。有什么办法可以解决这个问题吗?

您可以使用 Object.getOwnPropertyDescriptor 访问有权访问 hiddenState 的闭包。另外,如果你不需要修改 getter,根本就不要覆盖它,它会一直存在。

var oldSetter = Object.getOwnPropertyDescriptor(o, 'state').set;
Object.defineProperty(o, 'state', {
  set: function (s) {
    /* do something to s */
    oldSetter(s);
  }
});