在Math课程中,我们学习了如何定义新的运算符。例如:
(ℝ, ∘), x ∘ y = x + 2y
这定义了∘
法律。对于任何实数 x 和 y ,x∘y x + 2y 。
示例:2 ∘ 2 = 2 + 4 = 6
。
可以在JavaScript中定义这样的运算符吗?我知道一个函数可以完成这项任务:
function foo (x, y) { return x + 2 * y; }
但我希望使用以下语法:
var y = 2 ∘ 2; // returns 6
而不是:
var y = foo(2, 2);
这个问题最接近的解决方案是什么?
答案 0 :(得分:20)
简短的回答是否定的。 ECMAScript(标准JS基于)不支持运算符重载。
另外,在ECMAScript 7中,在设计自定义值类型时,您将能够重载标准运算符的子集。这是关于该主题的slide deck by language creator and Mozilla CTO Brendan Eich。但是,这不允许任意操作符,并且重载的含义只会应用于值类型。< - 哈哈最终没有发生。
可以使用第三方工具(如sweet.js)添加自定义运算符,但这需要额外的编译步骤。
我answered with a solution from outside JavaScript使用esprima - 这是更改 JavaScript并扩展它,它不是原生的。
答案 1 :(得分:3)
没有。 JavaScript不支持运算符重载。但你可以制作一个类方法来做这个
var mathClass = function(value){
this.value = value;
}
mathClass.prototype.toLaw = function(){
return 2 * this.value;
}
var y = new mathClass(2)
2 + y.toLaw(); //2 + 2 * y
答案 2 :(得分:3)
您可以通过Number.prototype
上的方法添加伪运算符:
Object.defineProperty(Number.prototype, 'myOp', {
value: function(that) {
return this + 2 * that;
}
});
然后所有这些语法都能正常工作
alert( (2).myOp(2) )
alert( 2 .myOp(2) )
alert( 2..myOp(2) )
alert( 2.0.myOp(2) )
2.myOp(2)
不起作用,因为句点被视为小数点
答案 3 :(得分:2)
没有。你不能在JS中做到这一点。
最接近IMO的是实现自己的对象,该对象具有可链接的界面,即“流畅”的语法。这样你就可以像按顺序说出来一样操作。
var eq = new YourEquationObject();
// Then operate like 1 - 2 * 3
eq.add(1).sub(2).mul(3);
细节取决于你。只是给出一个想法。
答案 4 :(得分:2)
已编译为JS语言的集支持自定义运算符。
我将突出显示ReasonML(ocaml语法可读的js语法)和Bucklescript(ocaml-to-js编译器),它们使自定义运算符看起来很整洁:
例如,用于连接字符串的运算符可能看起来像:
let (>|<) = (list, seperator) => Belt.List.reduce(list, "", (a, b) => a ++ seperator ++ b);
然后可以像这样使用:
[Styles.button, Media.Classes.atLeastTablet] >|< " "
所有这些缺点的一个事实是它必须使用这种可编译为js的语言编写,并且具有很多优点和缺点,但是通常这些语言具有大量您不喜欢的语法糖的吸引力。不会进入js / ts
答案 5 :(得分:1)
阅读答案下方的评论。
显然你做不到。这是关闭的事情:
function exec(input) {
return Function(
'return ' + input.replace(/∘( *[\d.]+)/g, '+ 2 * $1') + ';'
)();
}
exec('2 ∘ 2'); // 6
答案 6 :(得分:1)
稍长一点,那么短的是你可以,但是它比你在Math class中所做的更多参与
要使用新构造扩展语言,您可以使用http://esprima.org/之类的转换器或任何其他变换器。您需要定义语法,编写解析器来解析语句,最后添加实际代码来完成数学部分。当这些部分到位后,您已经创建了一种新的语言,它可以像javascript一样工作,但增加了对∘
运算符的支持。
它真的不是 很难添加新语法,这里是facebooks示例他们如何添加=&gt;箭头函数语法
https://github.com/facebook/jstransform/blob/master/visitors/es6-arrow-function-visitors.js
答案 7 :(得分:1)
鉴于ES6中添加了一些新的标记模板文字功能,因此可以创建自定义DSL来处理诸如包含不同代数符号的嵌入式表达式。
例如(在stackblitz中运行)
function math(strings, x, y) {
// NOTE: Naive approach as demonstration
const operator = strings[1].replace(/\s/gi, "");
if (operator == "∘") {
return x + 2 * y;
}
else if (operator == "^") {
return Math.pow(x, y);
}
else {
return `Unknown operator '${operator}'`;
}
}
console.log(math`${2} ∘ ${2}`)
请注意,由于带标签的模板文字不一定会返回字符串作为结果,因此它们可以返回更复杂的中间AST之类的结构来构建一个表达式,然后可以对其进行进一步完善和解释,同时保持与领域特定语言接近。我还没有找到任何现成的库可以对Java脚本执行此操作,但是从我对带标签的模板文字的了解以及在lit-html等地方的用法来看,这应该是一个有趣且可以平易近人的工作。
答案 8 :(得分:0)
我也在问这个问题,这是我的回答:
function myCustomOperation(string){
var res = String.fromCharCode(9762);
var thing = string.replace(/☢/g," + 10 + ");
thing=thing.replace(/☣/g," * 2 + ");
thing=thing.replace(/☠/g," / 3 * ");
return [eval(thing),string+" = "+eval(thing)];
};
var thing = myCustomOperation("
3 ☠ 4
");
document.write(thing[1]);