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

时间:2017-02-04 14:50:36

标签: javascript es6-class

我想有一个类我可以指定“ A的实例a1,当你需要值”时,你将调用B的特定实例b1的函数computeValue()。我需要指定此实例将使用哪个实例的方法。

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

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()似乎更好。

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

2 个答案:

答案 0 :(得分:1)

使用函数几乎总是优先于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());
    }
}

答案 1 :(得分:1)

是的,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