将特定实例的特定方法作为参数传递

Pass specific method of a specific instance as parameter

我想要一个 class 可以指定“A 的实例 a1,当你需要值”。我需要指定这个实例将使用哪个实例的哪个方法。

到目前为止我找到了两个解决方案:

eval()解决方案:

class A {

  constructor(funcToCall) {
    this.funcToCall = funcToCall;
  }

  displayValue() {
    console.log(eval(this.funcToCall));
  }
}

class B {

  constructor(value) {
    this.value = value;
  }

  computeValue() {
    return this.value;
  }
}


var b1 = new B(1);
var a1 = new A("b1.computeValue()");
a1.displayValue();// Displays "1", okay

function.call()解决方案:

class A {

  constructor(funcToCall, instanceToCallItOn) {
    this.funcToCall = funcToCall;
    this.instanceToCallItOn = instanceToCallItOn;
  }

  displayValue() {
    console.log(this.funcToCall.call(this.instanceToCallItOn));
  }
}

class B {

  constructor(value) {
    this.value = value;
  }

  computeValue() {
    return this.value;
  }
}


var b1 = new B(1);
var a1 = new A(b1.computeValue, b1);
a1.displayValue(); // Displays "1", okay

所以对我来说 eval() 解决方案似乎很脏,而 function.call() 似乎更好。

哪种解决方案最好?这个问题有没有更优雅的解决方案?

使用函数几乎总是优于 eval()。你可以使用.bind()来简化第二种方法,这样你就不需要单独传递函数和实例了。

class A {
    constructor(funcToCall) {
        this.funcToCall = funcToCall;
    }

    displayValue() {
        console.log(this.funcToCall());
    }
}

// class B is the same as yours

var b1 = new B(1);
var a1 = new A(b1.computeValue.bind(b1));
a1.displayValue();

或者如果你仍然喜欢单独传递实例,你可以在构造函数中使用.bind()

class A {
    constructor(funcToCall, instance) {
        this.funcToCall = funcToCall.bind(instance);
    }

    displayValue() {
        console.log(this.funcToCall());
    }
}

是的,那个 eval 东西 非常 脏,如果 b1 不在正确的范围内,它甚至不会工作。使用 call 没问题,但您可以做得更好:

  • 传递实例和方法名的组合:

    class A {
      constructor(instance, methodName) {
        this.instance = instancen;
        this.methodToCall = methodName;
      }
    
      displayValue() {
        console.log(this.instance[this.methodToCall]());
      }
    }
    var a1 = new A(new B(1), "computeValue);
    
  • 传递一个执行方法调用的函数以及它自己需要的任何其他内容:

    class A {
      constructor(funcToCall) {
        this.funcToCall = funcToCall;
      }
    
      displayValue() {
        console.log(this.funcToCall());
      }
    }
    var b1 = new B(1);
    var a1 = new A(() => b1.computeValue());
    // or:   new A(b1.computeValue.bind(b1))
    // or anything else