JavaScript类是否具有与Python类的__call__等效的方法?

con*_*xyz 6 javascript python

在Python中,您可以__call__()为类实现,这样,调用类本身的实例即可执行该__call__()方法。

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

e = Example()
e() # "the __call__ method" 
Run Code Online (Sandbox Code Playgroud)

JavaScript类是否具有等效的方法?

编辑

在此处合并讨论的摘要答案:

  • Python和JavaScript对象的相似度不足以实现真正的等同度(原型与基于类self、、与this
  • 可以使用代理或修改原型来实现该API ,并且可以使用bind
  • 人们通常不应该这样做:它与JS的结构以及JavaScript的正常使用相距太远,有可能在其他JS开发人员,您的未来自我中造成混乱,并可能导致特有的副作用。

Cer*_*nce 5

唯一的方法是让构造函数显式返回一个可以调用的函数。(在Javascript中,如果未return在构造函数中显式地返回,则返回新创建的实例-但这样的实例将是一个普通对象,而不是函数。)

class Example {
  constructor() {
    return function() {
      console.log('function running');
    }
  }
}

const e = new Example();
e();
Run Code Online (Sandbox Code Playgroud)

但这确实很奇怪,并且不允许您引用原型中的任何属性或类似内容。最好避免使用它,或者制作一个返回函数的普通函数:

const example = () => () => console.log('function running');
const e = example();
e();
Run Code Online (Sandbox Code Playgroud)


Mar*_*yer 5

我基本上同意 @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
Run Code Online (Sandbox Code Playgroud)

我真的不确定这是否是一个好主意,但这是一个有趣的实验。