JavaScript中动态类型运算符的双重调度
Double dispatch for dynamically typed operators in JavaScript
我想用这样一种方式来公式化代数表达式,即可以交换底层的数字类型。如果你想的话,想想复数、大整数、矩阵等等。出于这个原因,我会写add(a, b)
或a.add(b)
而不是a + b
。在静态类型语言中,我只需使用函数add
的基于类型的重载来实现各种替代方案。但对于JavaScript来说,这不起作用,所以我正在寻找替代方案。执行的方法取决于两个操作数的类型。
我想到的一种方法是以下双重调度机制:
-
将表达式写成
a.add(b)
。 -
对于给定的类型(例如,我自己的
Complex
类型或内置的Number
类型),可以通过以下方式实现该方法:add: function(that) { that.addComplex(this); }
因此,第二个调用的方法名对其中一个操作数的类型进行编码。
-
采用专门的方法来处理所有组合。例如,设置
Number.prototype.addComplex = function(that) { return newComplex(that.real + this, that.imaginary); }
假设我知道所有类型,这样我就可以确保处理所有组合。现在让我困扰的是这些对象的创建。
上面的方法在很大程度上依赖于虚拟方法调度,所以在我看来,它需要某种继承。经典的构造函数没有问题,但根据我刚刚做的这个jsperf,使用构造函数创建对象往往比对象文字慢。有时速度会慢很多,比如本例中的Firefox。因此,我不愿意为每个产生这种开销,例如,复数值的数字中间值,只是为了让我的运算符重载工作。
我在这个jsperf中尝试的另一种方法是不使用原型,而是将虚拟方法存储为每个对象实例的属性。在几乎所有测试过的浏览器上运行速度都很快,但这里我担心对象的大小。我担心对象有两个实际的浮点值,但可能有多达50个不同的成员函数来处理所有成对的运算符重载。
第三种方法是使用单个add
函数,该函数以某种方式检查其自变量的类型,然后根据该类型做出决策。可能在由一些数字类型标识符的组合索引的某个列表中查找实际实现。我还没有把它写出来进行测试,但这种类型检查感觉很慢,我也怀疑JIT编译器是否能够优化这种奇特的函数调度。
有没有什么方法可以欺骗当前的JavaScript实现,让它们对创建成本低廉且不占用过多内存的对象进行适当的优化双重调度?
第三种方法看起来很可行:
function Complex(re, im) {
return {type:'c', re:re, im:im }
}
function Real(n) {
return {type:'r', n:n }
}
funcs = {
add_c_r: function(a, b) {
console.log('add compl to real')
},
add_r_c: function(a, b) {
console.log('add real to compl')
}
}
function add(a, b) {
return funcs["add_" + a.type + "_" + b.type](a, b);
}
add(Complex(1, 2), Real(5))
add(Real(5), Complex(1, 2))
一个额外的字段+一个间接寻址是合理的成本。
- 这是什么 ==- javascript 运算符
- jQuery/JS包含运算符或类似运算符
- Javascript逻辑运算符和字符串/数字
- 模运算符前的双水平线
- jQuery's trim()的前缀为not运算符
- Javascript,如果条件在没有&&逻辑运算符当&&它不起作用
- 调度没有'无法立即更新组件
- 在dhtmlx调度程序中多次触发OnEventSave
- 如果在构造函数中有“返回”,则在 JavaScript 中的新运算符中做了什么
- 如何使用排列运算符来获取具有命名参数的函数的所有参数
- JavaScript 中三元条件和逻辑和运算符的运算符优先级
- 用于验证JS中逻辑运算符表达式的正则表达式
- 什么's是相当于LINQ's SelectMany运算符
- JavaScript-===vs===运算符性能
- 在 Jquery/Javascript 中使用多个 OR (||) 运算符时如何设置变量
- 三元运算符检查多个字符串
- 调用C++中JScript中的instanceof运算符(IDispatch/IDispatchEx)
- ||(OR)运算符如何在赋值中工作
- 在 JavaScript 对象中设置要使用的运算符的属性
- JavaScript中动态类型运算符的双重调度