使用类方法作为回调时的Promise.then执行上下文

Ser*_*gio 9 javascript promise ecmascript-6 es6-promise

为什么在使用类方法作为回调时以及使用"普通函数" 时Promise.then传递执行上下文?undefinedwindow

类方法是否与其拥有的对象/类分离?为什么undefined而不是window

function normal() {
    console.log('normal function', this);
}
const arrow = () => {
    console.log('arrow function', this);
}

function strictFunction() {
    'use strict';
    console.log('strict function', this);
}

class Foo {
    test() {
        this.method(); // Foo
        Promise.resolve().then(() => console.log('inline arrow function', this)); // Foo
        Promise.resolve().then(normal); // window
        Promise.resolve().then(arrow); // window
        Promise.resolve().then(strictFunction); // undefined
        Promise.resolve().then(this.method); // undefined <-- why?
    }

    method() {
        console.log('method', this);
    }
}

const F = new Foo();
F.test();
Run Code Online (Sandbox Code Playgroud)

(jsFiddle)

我希望上下文this.method丢失,但无法理解为什么this.method"正常"和箭头功能之间的不同行为.

这种行为有规格吗?我发现的唯一参考是Promises A +,指的是"在严格的模式下this将在undefined里面;在草率模式下,它将是global object." .

nem*_*035 8

你在那里的引用告诉你为什么:

在严格模式下this将是未定义的; 在草率模式下,它将成为全局对象.

ES6规范说:

ClassDeclaration或ClassExpression的所有部分都是严格模式代码

因此,由于严格模式,this在一个未绑定的类方法中,将是undefined.

class A {
  method() {
    console.log(this);
  }
}

const a = new A();
a.method(); // A
const unboundMethod = a.method;
unboundMethod(); // undefined
Run Code Online (Sandbox Code Playgroud)

如果您使用严格模式传递普通函数,则会产生相同的行为,因为默认情况下this绑定undefined在严格模式下,而不是设置为全局对象.

其原因normalarrow具有this作为window是因为它们不是在类中,因此不包裹在严格模式.


至于承诺和then方法,它只会通过undefined作为this,但将不会覆盖已经绑定this.

如果你看看PromiseReactionJob规范:

具有参数reaction和argument的作业PromiseReactionJob将适当的处理程序应用于传入值,并使用处理程序的返回值来解析或拒绝与该句柄关联的派生promise.

...
let handlerResult be Call(handler, undefined, «argument»).
Run Code Online (Sandbox Code Playgroud)

Call的第二个参数是this值,设置为undefined.


Omr*_*ron 5

这与Promise无关,而是与this调用上下文有关。

情况1:

this.method(); // Foo
Run Code Online (Sandbox Code Playgroud)

method是在Foo类中定义的函数,因此this被评估为触发该函数的对象,位于thisthis.method。因此- Foo显示。

情况2:

Promise.resolve().then(() => console.log('inline arrow function', this)); // Foo
Run Code Online (Sandbox Code Playgroud)

箭头函数是ES6的一项功能,其独特的属性this是定义所在上下文的上下文中的上下文。该函数是在上下文中调用的,this === Foo这就是所显示的内容。

情况3:

Promise.resolve().then(normal); // window
Promise.resolve().then(arrow); // window
Run Code Online (Sandbox Code Playgroud)

由于箭头函数是箭头函数,所以箭头函数将其上下文保留为窗口,并且在没有上下文的情况下评估普通函数,在非上下文中将其this评估为窗口strict mode

情况4:

Promise.resolve().then(strictFunction); // undefined
Run Code Online (Sandbox Code Playgroud)

strict mode在此函数的主体内,由于请求是在窗口中声明的,this被评估为未定义。

情况5:

Promise.resolve().then(this.method); // undefined <-- why?
Run Code Online (Sandbox Code Playgroud)

在此规范中,定义所有类代码均为严格代码:

ClassDeclaration或ClassExpression的所有部分都是严格模式代码。