Reputation: 1553
Here is the code where I lose the context when using the spread operator.
Look at function "decorator". Line when I lose context is marked with "ERROR"
/** MethodDecorator example */
class Account {
public firstName: string;
public lastName: string;
public constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}
@decorator
public sayMessage(msg: string): string {
return `${this.firstName} ${this.lastName}: ${msg}`
}
}
function decorator(target: any, key: string, desc: any): any {
let originDesc = desc.value;
desc.value = function(...args: any[]): any {
return originDesc(...args); // ==> ERROR: context lost
//return originDesc.apply(this, arguments); // ==> all OK
};
return desc;
}
let persone = new Account('John', 'Smith');
let message = persone.sayMessage('Hello world!');
console.log(message); // ==> undefined undefined: Hello world!
As far as I understand originDesc(...args);
equals originDesc.apply(this, arguments);
so why is my context lost?
Upvotes: 1
Views: 383
Reputation: 96959
That's because you set:
let originDesc = desc.value; // This is where you loose context
and then call originDesc
. This is exactly the same case as described here: How to access the correct `this` context inside a callback?.
Also, originDesc(...args)
compiles into originDesc.apply(void 0, args)
. (void
because it has not context binded, you can test it on https://www.typescriptlang.org/play/)
Upvotes: 2
Reputation: 1075079
As far as I understand originDesc(...args); equals originDesc.apply(this, arguments); so why context is lost?
No, it doesn't. It's equivalent to originDesc(args[0], args[1], /*etc.*/)
, which uses the default this
(the global object in loose mode, undefined
in strict mode).
In that code, you'll need to use .apply
:
originDesc.apply(appropriateThisValueHere, args);
or .call
:
originDesc.call(appropriateThisValueHere, ...args);
According to this comment in the code:
//return originDesc.apply(this, arguments); // ==> all OK
appropriateThisValue
would be this
, so either:
originDesc.apply(this, args);
or
originDesc.call(this, ...args);
Upvotes: 2