在Python中,您可以为一个类实现__call__()
,以便调用该类的实例本身即可执行__call__()
方法。
class Example:
def __call__(self):
print("the __call__ method")
e = Example()
e() # "the __call__ method"
JavaScript类是否具有等效的方法?
修改
在此处包含讨论的摘要答案:
self
,与this
的相似性不够)bind
来实现API ?答案 0 :(得分:5)
唯一的方法是让构造函数显式返回一个可以调用的函数。 (在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();
答案 1 :(得分:4)
我基本上同意@CertainPerformace的观点,这实际上不是您在普通JS代码中会做的事情。话虽如此,代理提供了很多可能性,您可以创建出与Python的__call__()
接近(表面上)出乎意料的东西。
例如:
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 for demo purposes
yield *this.arr.map(this) // call itself in a map!
}
}
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:
f.n = 2
// call it again with new __call__
console.log("calling with 10:", f(10)) // 10**2
console.log([...f]) // or iterate
我真的不确定这是否是一个好主意,但这是一个有趣的实验。
答案 2 :(得分:3)
您可以完成此操作,但是方式很怪异。
JavaScript中没有__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 { ... }'