为什么我在此代码中丢失了上下文?

时间:2016-11-08 10:19:19

标签: javascript typescript

以下是使用扩展运算符时丢失上下文的代码。

看功能“装饰”。丢失上下文时的行标有“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!

据我所知,originDesc(...args);等于originDesc.apply(this, arguments);,为什么我的背景会丢失?

2 个答案:

答案 0 :(得分:1)

那是因为你设置了:

let originDesc = desc.value; // This is where you loose context

然后拨打originDesc。这与此处描述的情况完全相同:How to access the correct `this` context inside a callback?

此外,originDesc(...args)会编译为originDesc.apply(void 0, args)。 (void因为它没有上下文绑定,您可以在https://www.typescriptlang.org/play/

上进行测试

答案 1 :(得分:1)

  

据我了解originDesc(... args);等于originDesc.apply(this,arguments);为什么背景会丢失?

不,它没有。它相当于originDesc(args[0], args[1], /*etc.*/),它使用默认的this(松散模式下的全局对象,严格模式下为undefined)。

在该代码中,您需要使用.apply

originDesc.apply(appropriateThisValueHere, args);

.call

originDesc.call(appropriateThisValueHere, ...args);

根据代码中的这条评论:

 //return originDesc.apply(this, arguments); // ==> all OK

appropriateThisValue将为this,因此:

originDesc.apply(this, args);

originDesc.call(this, ...args);