如何让JavaScript类实例支持函数式调用(如v(k))?
在JavaScript中让Vector实例支持v(k)式调用
可以通过JavaScript的内置特性实现,无需自定义预处理器,以下是两种可行方案:
方案一:让类继承Function
利用Function实例可被调用的特性,让Vector继承Function,并在构造阶段绑定调用逻辑:
class Vector extends Function { constructor(...vecElems) { super('k', 'return this.getElem(k)'); this.vecElems = vecElems; return this.bind(this); } getElem(k) { return this.vecElems[k]; } dot(v) { return this.vecElems.reduce((aV, cV, cI) => aV + cV * v.vecElems[cI], 0); } } const v = new Vector(3, 5, 7); console.log(v(2)); // 输出7 console.log(v.getElem(2)); // 输出7 console.log(v.dot(new Vector(4,6,8))); // 输出98
这种方式会让Vector实例同时拥有Function的原生方法(如bind、call),如果不需要这些额外特性,可选择下面的Proxy方案。
方案二:使用Proxy拦截调用操作
通过Proxy的apply陷阱,将实例的函数式调用转发到getElem方法:
class Vector { constructor(...vecElems) { this.vecElems = vecElems; return new Proxy(this, { apply(target, _, args) { return target.getElem(args[0]); } }); } getElem(k) { return this.vecElems[k]; } dot(v) { return this.vecElems.reduce((aV, cV, cI) => aV + cV * v.vecElems[cI], 0); } } const v = new Vector(3, 5, 7); console.log(v(2)); // 输出7 console.log(v.getElem(2)); // 输出7 console.log(v.dot(new Vector(4,6,8))); // 输出98
Proxy方案无需修改类的继承关系,仅通过拦截实现调用转发,更轻量化。
内容的提问来源于stack exchange,提问作者Ailurus
相关产品推荐
相关产品推荐

