Open mixtur opened 8 years ago
const a = new A();//this invokes console.log
I think it should not invoke console.log
, decorator works in design time so console.log
is invoked when you define class A
but not when you intantiate it
let decorator = x => {
console.log(1);
return x;
};
@decorator
class A {
}
new A();
new A();
This code only log once.
For the new A()
statement in foo
method, it depends on how decorator is implemented:
let decorator = x => {
x.prototype.bar = () => {
console.log('bar');
};
return x;
};
@decorator
class A {
foo() {
let a = new A();
a.bar();
}
}
let a = new A();
a.foo();
This code successfully prints bar
because decorator modifies the prototype of class A and add a method bar, so new A()
just contains a bar
method.
let decorator = x => class extends x {
bar() {
console.log('bar');
}
};
@decorator
class A {
foo() {
let a = new A();
a.bar();
}
}
let a = new A();
a.bar();
a.foo();
However this should throw a TypeError
when a.foo()
is called because decorator returns a subclass of A so new A()
does not contains method bar
To reference the actual decorated subclass in method foo
you could change new A()
to new this.constructor()
, it always works
I see why my example is not actualy showing the problem. Your last is better And you provided some way to access decorated class. I figured one can also apply decorator manually and have access to both versions.
const A = decorator(class B {
a() { return new A(); }
b() { return new B(); }
})
But still.
Does anyone ever need to access original class from itself when it is decorated using @decorator
syntax?
If not, I think the opposite behaviour is better.
It's pretty interesting why I believe the new A()
state in foo
method points the original class A but not the decorated one, in fact outside the class body the reference to A
is the decorated version of class:
let decorator = x => class extends x {
bar() {
console.log('bar');
}
};
@decorator
class A {
foo() {
console.log(A); // outputs [Function: A]
let a = new A();
a.bar();
}
}
console.log(A); // outputs [Function: _class] but not [Function: A]
I think it is because:
A
inside class body be the decorated versionFor language itself, I think there should be cases where we need both the original version and decorated version of class, a good example is C# which has both virtual and non-virtual methods along with override
and new
keyword for methods, in javascript world, A.prototype.bar.call(this)
is the non-virtual one and this.bar()
is the virtual one
To addition, there is a more tricky way to access both original and decorated version of class:
let B = @decorator class A {
foo() {
console.log(A); // Original one
console.log(B); // Decorated one
}
};
let a = new B();
a.foo();
It's the same as apply decorator manually
When you have decorated class, from inside that class should you be able to access decorated or original version of it?
For example.