这不是正确的实例

时间:2019-04-18 19:23:25

标签: javascript ecmascript-6

我有这两个课程

class Foo {
    name = 'Foo';

    foo() {
        const bar = new Bar(this.onSomething);
        bar.bar();
    }

    onSomething() {
        console.log(this);        //<= this where thing goes weird
    }
}

class Bar {
    name = 'Bar';
    constructor(onSomethingCallback) {
        this.onSomethingCallback = onSomethingCallback;
    }

    bar() {
        this.onSomethingCallback();
    }
}

const a = new Foo();
a.foo();

当名为onSomething的方法this引用Bar类的实例而不是Foo类时。

我希望this引用Foo的实例,因为方法onSomethingFoo

3 个答案:

答案 0 :(得分:1)

这是预期的。如果绑定this.onSomething,则将设置其this,否则,将根据其调用源确定其this

这也是const $ = document.getElementById;不可用,但const $ = document.getElementById.bind(document);可用的原因(因为getElementById可能引用了this)。

class Foo {
    name = 'Foo';

    foo() {
        const bar = new Bar(this.onSomething.bind(this));
        bar.bar();
    }

    onSomething() {
        console.log(this);        //<= this where thing goes weird
    }
}

class Bar {
    name = 'Bar';
    constructor(onSomethingCallback) {
        this.onSomethingCallback = onSomethingCallback;
    }

    bar() {
        this.onSomethingCallback();
    }
}

const a = new Foo();
a.foo();

有关thisbind的更多信息,请参见mdn。

答案 1 :(得分:1)

不是,这就是JS函数的工作方式。将函数调用为foo.bar()会将您传递给foo作为this上下文(如果可以的话,第0个参数)。名为this/* Bar */.onSomethingCallback()的函数不记得它曾经是另一个对象的属性。

还有一些箭头函数,它们仅采用词法this

class Foo {
    name = 'Foo';

    foo = () => {
        const bar = new Bar(this.onSomething);
        bar.bar();
    }

    onSomething = () => {
        console.log(this);        //<= this where thing goes weird
    }
}

class Bar {
    name = 'Bar';
    constructor(onSomethingCallback) {
        this.onSomethingCallback = onSomethingCallback;
    }

    bar = () => {
        this.onSomethingCallback();
    }
}

const a = new Foo();
a.foo();

答案 2 :(得分:0)

您正在暂时丢失Foo的上下文,因为在这一行this.onSomethingCallback = onSomethingCallback;中,您只是将该函数置于“上下文之外”并从Bar实例中调用它。

有几种首选的解决方案:

  1. onSomething构造函数中绑定Foo
class Foo {
  constructor () {
    this.onSomething = this.onSomething.bind(this);
  }
  ...
}
  1. 以箭头样式编写onSomething函数
class Foo {
  onSomething = () => {...}
  ...
}
  1. onSomething函数绑定到Bar实例之前
class Foo {
  foo() {
    const bar = new Bar(this.onSomething.bind(this));
    ...
  }
  ...
}