在JavaScript中捕获内部调用者的“this”

时间:2018-04-09 12:41:40

标签: javascript ecmascript-6

请考虑以下代码:

class Abc {
  funcAbc() {
    console.log(this);
  }
}

const abc = new Abc();

class Def {
  constructor(func) {
    this.func = func;
  }

  runFunc() {
    this.func();
  }
}

const def = new Def(abc.funcAbc);
def.runFunc();

我希望在调用thisAbcrunFunc,但在上述实施中,this内的runFunc指的是Def 。我理解这种情况正在发生,因为runFunc是班级Def的成员。但有没有办法可以捕获“原this',即在this内点AbcrunFunc

我不能const def = new Def(abc.funcAbc.bind(abc)因为课堂消费者不应该为设置this背景而烦恼。

注意:这不是一个理论问题,它是我正在进行的项目中的实际要求。包装器类接受config,其中一部分是函数。此函数也可以是类实例上的方法,在其中使用this。因此,我需要在包装类this内调用函数时保留原始Def

2 个答案:

答案 0 :(得分:1)

您正在寻找bind()(或其中一种变体)。

class A {
  constructor() {
    this.hello = "hello";
  } 

  run() {
    console.log(this.hello);
  }
}

class B {
  constructor(func) {
    this.func = func;
  }
  
  run() {
    this.func();
  }
}

const a = new A();
const b = new B(a.run.bind(a));

b.run();

当你bind()一个函数时,它会在函数运行时锁定函数内的this,无论它是如何被调用的。

你也可以在闭包中包装函数:

class A {
  constructor() {
    this.hello = "hello";
    
    this.run = ((self) => () => console.log(self.hello))(this);
  } 
}

class B {
  constructor(func) {
    this.func = func;
  }
  
  run() {
    this.func();
  }
}

const a = new A();
const b = new B(a.run);

b.run();

或者您可以使用箭头函数语法。注意,这个需要Babel class properties transform插件才能工作:

class A {
  constructor() {
    this.hello = "hello";
  } 

  run = () => {
    console.log(this.hello);
  }
}

class B {
  constructor(func) {
    this.func = func;
  }
  
  run() {
    this.func();
  }
}

const a = new A();
const b = new B(a.run);

b.run();

答案 1 :(得分:0)

使用function.call(thisArg, args...)可以将this设置为您想要的内容。即,你可以这样做:

class Abc {
  func() {
    console.log(this);
  }
}

const abc = new Abc();

class Def {
  constructor(source) {
    this.func = source.func;
    this.source = source;
  }

  runFunc() {
    this.func.call(this.source);
  }
}

const def = new Def(abc);
def.runFunc();

此解决方案假设abc上有一个名为func的方法。