处理Node.JS中类的函数调用

时间:2017-04-20 15:45:21

标签: node.js

假设你有一个班级

class MyClass {
    world() {
        console.log("hello world");
    }
}

我可以运行类似于以下的方法:

var hello = new MyClass();
hello.world();
# outputs: hello world

有没有办法处理对象的直接函数调用?例如:

hello();

返回:TypeError: hello is not a function

我可以将此调用设为默认功能吗?例如,类似于PHP's invoke function ...

1 个答案:

答案 0 :(得分:3)

我们只能在JavaScript中创建可调用的东西,如果该东西是某个对​​象,在某些时候委托给Function.prototype。因此,我们的课程需要来自extend Function s extend的班级extendFunction。我们还需要能够从类对象中访问实例变量(以便调用invoke()),因此需要将其绑定到自身。此绑定只能在构造函数中发生。

由于我们的课程将继承Function,因此我们需要先致电super才能使用this。但是,Function构造函数实际上需要一个我们不会拥有的代码字符串,因为我们希望以后能够设置invoke。所以我们需要extend Function在一个不同的类中,它将是我们类的父类,它将完成设置我们的虚函数的原型的工作(我们需要它才能够调用返回的对象)。将所有这些结合在一起,我们得到:



class ExtensibleFunction extends Function { 
  constructor(f) {                          
    // our link to Function is what makes this callable,
    // however, we want to be able to access the methods from our class
    // so we need to set the prototype to our class's prototype.
    return Object.setPrototypeOf(f, new.target.prototype);
  }
}

class MyClass extends ExtensibleFunction {
  constructor() {
    // we build an ExtensibleFunction which accesses 
    // the late-bound invoke method
    super(function() { return this.invoke(); });
    return this.bind(this); // and bind our instance 
                            // so we have access to instance values.
  }

  invoke() {
    console.log("Hello, world!");
  }
}

x = new MyClass();
x(); //prints "Hello, world!"




我主要采用this answer中的技术来实现这一目标。

使用此技术的一个有趣方面是,您可以将MyClass命名为Callable并删除invoke方法 - 然后extends Callable将变为可调用的任何类只要它有一个invoke()方法。事实上......



class ExtensibleFunction extends Function { 
  constructor(f) {                          
    // our link to Function is what makes this callable,
    // however, we want to be able to access the methods from our class
    // so we need to set the prototype to our class's prototype.
    return Object.setPrototypeOf(f, new.target.prototype);
  }
}

class Callable extends ExtensibleFunction {
  constructor() {
    // we build an ExtensibleFunction which accesses 
    // the late-bound invoke method
    super(function() { return this.invoke(); });
    return this.bind(this); // and bind our instance 
                            // so we have access to instance values.
  }
}

class CallableHello extends Callable {
  invoke() {
    console.log("Hello, world!");
  }
}

class CallableBye extends Callable {
  invoke() {
    console.log("Goodbye cruel world!");
  }
}

x = new CallableHello();
x(); //prints "Hello, world!"

y = new CallableBye();
y(); //prints "Goodbye cruel world!"




(当然,您可以通过在函数对象上设置属性来获得相同的效果,但我认为这更加一致)