在 JavaScript 中修饰实例方法时出现问题

Problems decorating an instance method in JavaScript

本文关键字:问题 实例方法 JavaScript      更新时间:2023-09-26

我在 ES6 中装饰实例方法时遇到了一个难题。我在装饰该方法时没有问题,但似乎它被类实例的单一状态所困扰。这是我具体处理的内容:

class Test {
    init() {
        this.foo = 'bar';
    }
    @decorator
    decoratedMethod() {
        console.log(this.foo); // undefined
    }
}
let test = new Test();
test.init();
test.decoratedMethod();
function decorator(target, name, descriptor) {
     let fn = target[ name ].bind(target, 'a', 'b');
     return fn;
}

意识到上面的代码正在做它应该做的事情,但是如果我想访问添加到范围内的foo和其他属性,我该如何装饰decoratedMethod并仍然绑定新的函数属性?

方法修饰器在类声明时运行一次,而不是在类实例化时运行一次。这意味着示例中的targetTest.prototype,而不是实例。所以你的例子本质上是:

class Test {
  init() {
    this.foo = 'bar';
  }
  decoratedMethod() {
    console.log(this.foo); // undefined
  }
}
Test.prototype.decoratedMethod = 
    Test.prototype.decoratedMethod.bind(Test.prototype, 'a', 'b');

这应该清楚地说明为什么你的代码失败了。要绑定的对象没有foo属性,只有实例具有。

如果您希望为每个实例

处理装饰器,事情会变得更加复杂,您需要在创建实例后进行绑定。一种方法是

function decorator(target, name, descriptor){
  const {value} = descriptor;
  delete descriptor.value;
  delete descriptor.writable;
  descriptor.get = function(){
    // Create an instance of the bound function for the instance.
    // And set an instance property to override the property
    // from the object prototype.
    Object.defineProperty(this, name, {
      enumerable: descriptor.enumerable,
      configurable: descriptor.configurable,
      value: value.bind(this, 'a', 'b'),
    });
    return this[name];
  };
}