Есть ли у классов JavaScript метод, эквивалентный классам Python __call__?

В Python вы можете реализовать __call__() для класса так, чтобы вызов экземпляра самого класса __call__() метод __call__() .

class Example:
    def __call__(self):
        print("the __call__ method")

e = Example()
e() # "the __call__ method" 

У классов JavaScript есть эквивалентный метод?

Всего 3 ответа


Единственный способ сделать это - явным образом вернуть конструктору функцию, которую можно вызвать. (В Javascript, если вы не return явным образом внутри конструктора, только что созданный экземпляр будет возвращен - но такой экземпляр будет простым объектом, а не функцией.)

 class Example { constructor() { return function() { console.log('function running'); } } } const e = new Example(); e(); 

Но это было бы очень странно и не позволяло бы вам ссылаться на какие-либо свойства прототипа или что-то подобное. Лучше избежать этого или создать простую функцию, которая возвращает функцию:

 const example = () => () => console.log('function running'); const e = example(); e(); 


Вы можете сделать это, но довольно странным способом.

В __call__() нет ничего подобного __call__() , __add__() или __sub__() - JavaScript не поддерживает перегрузку операторов.

Однако, если вы действительно хотите сделать объекты вызываемыми, вы можете сделать это, предоставив функции другой прототип:

 function createCallableObject(cls, fn) { // wrap the original function to avoid modifying it const wrapper = (...args) => fn(...args) // set the prototype of the wrapped function so we can call class methods Object.setPrototypeOf(wrapper, cls.prototype) return wrapper } class Example { method() { console.log('This is an instance of class Example') } } function example() { console.log('This is a function') } const obj = createCallableObject(Example, example) obj() // 'This is a function' obj.method() // 'This is an instance of class Example' console.log(obj.constructor) // 'class Example { ... }' 


Я в основном согласен с @CertainPerformace, что это на самом деле не вещь JS. Сказав, что вы можете избежать неприятностей с прокси. Например:

 class F extends Function{ constructor(someID, arr, n){ super() this.id = someID this.arr = arr this.n = n return new Proxy(this, { apply(target, thisArg, argumentsList) { return target.__call__(...argumentsList); } }) } __call__(a){ // simple mult functions return a * this.n } *[Symbol.iterator](){ // make it iterable -- call itself over it's array prop yield *this.arr.map(this) // <-- hmm, that looks weird } } let f = new F("FrankenFunction", [1, 2, 3, 4], 5) // access instance variable console.log("id:", f.id) // call it console.log("calling with 100: ", f(100)) // use the iterator // get multiples of calling this on arr console.log([...f]) // change the __call__ function to power instead F.prototype.__call__ = function(a){ return a ** this.n } // change n to get squares: fn = 2 // call it again with new __call__ console.log("calling with 10:", f(10)) // 10**2 console.log([...f]) // or iterate 

Я не думаю, что рекомендовал бы это для чего-либо кроме любопытства.


Есть идеи?

10000