JavaScript 中装饰实例方法的问题
Problems decorating an instance method in JavaScript
我在 ES6 中装饰实例方法时遇到了难题。我在装饰该方法时没有遇到任何问题,但它似乎停留在 class 实例的单一状态。这是我正在处理的具体内容:
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
并且仍然绑定新函数属性?
方法装饰器 运行 在 class 声明时使用一次,而不是在实例化 class 时。这意味着您示例中的 target
是 Test.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];
};
}
我在 ES6 中装饰实例方法时遇到了难题。我在装饰该方法时没有遇到任何问题,但它似乎停留在 class 实例的单一状态。这是我正在处理的具体内容:
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
并且仍然绑定新函数属性?
方法装饰器 运行 在 class 声明时使用一次,而不是在实例化 class 时。这意味着您示例中的 target
是 Test.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];
};
}