是否可以在JavaScript中创建自定义运算符?

时间:2013-12-22 10:36:09

标签: javascript operators

在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);

这个问题最接近的解决方案是什么?

9 个答案:

答案 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]);