我可以在Javascript中定义自定义运算符重载吗?

时间:2011-01-15 14:26:01

标签: javascript vector operator-overloading dsl equality

是否可以在JavaScript中的类型实例之间定义自定义运算符?

例如,假设我有自定义矢量类,是否可以使用

vect1 == vect2

检查是否相等,而底层代码是这样的?

operator ==(a, b) {
    return a.x == b.x && a.y == b.y && a.z == b.z;
}

(当然这是无稽之谈。)

7 个答案:

答案 0 :(得分:9)

我同意矢量原型上的相同功能是最佳解决方案。请注意,您还可以通过链接构建其他类似中缀的运算符。

function Vector(x, y, z) {
    this.x = x;
    this.y = y;
    this.z = z;
}

Vector.prototype.add = function (v2) {
    var v = new Vector(this.x + v2.x,
                       this.y + v2.y,
                       this.z + v2.z);
    return v;
}

Vector.prototype.equal = function (v2) {
    return this.x == v2.x && this.y == v2.y && this.z == v2.z;
}

您可以看到online sample here

更新:以下是创建支持链接的Factory function的更广泛示例。

答案 1 :(得分:8)

不,JavaScript不支持运算符重载。您需要编写一个执行此操作的方法:

Vector.prototype.equalTo = function(other) {
    if (!(other instanceof Vector)) return false;
    return a.x == b.x && a.y == b.y && a.z == b.z;
}

然后您可以使用以下方法:

vect1.equalTo(vect2)

答案 2 :(得分:8)

如果您想坚持使用==运算符,那么您可以做到最好:

function Vector(x, y, z) {
  this.x = x;
  this.y = y;
  this.z = z;
}

Vector.prototype.toString = function () {
  return this.x + ";" + this.y + ";" + this.z;
};

var a = new Vector(1, 2, 3);
var b = new Vector(1, 2, 3);
var c = new Vector(4, 5, 6);


alert( String(a) == b ); // true
alert( String(a) == c ); // false
alert( a == b + "" );    // true again (no object wrapper but a bit more ugly)

答案 3 :(得分:4)

不,这不是规范的一部分(这并不意味着没有some hacks)。

答案 4 :(得分:3)

您可以在JavaScript中更改对象的内置方法,例如valueOf()方法。对于任何两个对象来应用以下运算符>, <, <=, >=, -, + JavaScript获取每个对象的属性valueOf(),因此它处理运算符类似于:obj1.valueOf() == obj2.valueOf()(这在幕后)。您可以根据需要覆盖valueOf()方法。例如:

var Person = function(age, name){
    this.age = age;
    this.name = name;
} 

Person.prototype.valueOf(){
    return this.age;
}

var p1 = new Person(20, "Bob"), 
    p2 = new Person(30, "Bony");

console.log(p1 > p2); //false
console.log(p1 < p2); //true
console.log(p2 - p1); //10
console.log(p2 + p1); //40

//for == you should the following
console.log(p2 >= p1 && p2 <= p1); // false

所以这不是你问题的准确答案,但我认为这对于那类问题来说可能是一个有用的东西。

答案 5 :(得分:1)

这是一个简单的模拟,使用guard operator

测试相等性
function operator(node)
  {
  // Abstract the guard operator
  var guard = " && ";
  // Abstract the return statement
  var action = "return ";
  // return a function which compares two vector arguments
  return Function("a,b", action + "a.x" + node + "b.x" + guard + "a.y" + node + "b.y" + guard + "a.z" + node + "a.z" );
  }

//Pass equals to operator; pass vectors to returned Function
var foo = operator("==")({"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3});
var bar = operator("==")({"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6});

//Result
console.log(["foo",foo,"bar",bar]);
  

对于非严格模式函数,数组索引(在15.4中定义)命名数据属性的参数对象,其数字名称值小于相应函数对象的形式参数的数量,最初与相应的参数绑定共享它们的值在函数的执行上下文中。这意味着更改属性会更改参数绑定的相应值,反之亦然。如果删除并重新定义此属性或将属性更改为存取属性,则此对应关系将被破坏。对于严格模式函数,arguments对象的属性值只是传递给函数的参数的副本,并且属性值和形式参数值之间没有动态链接。

<强>参考

答案 6 :(得分:1)

这不是你问题的直接答案,但值得注意。

PaperScript是JavaScript的一个简单扩展,它增加了对任何对象的操作符重载的支持。

它用于在HTML5 Canvas上制作矢量图形。

它使用type =“text / paperscript”:

将PaperScript解析为脚本标记上的JavaScript
<!DOCTYPE html>
<html>
<head>
<!-- Load the Paper.js library -->
<script type="text/javascript" src="js/paper.js"></script>
<!-- Define inlined PaperScript associate it with myCanvas -->
<script type="text/paperscript" canvas="myCanvas">
  // Define a point to start with
  var point1 = new Point(10, 20);

  // Create a second point that is 4 times the first one.
  // This is the same as creating a new point with x and y
  // of point1 multiplied by 4:
  var point2 = point1 * 4;
  console.log(point2); // { x: 40, y: 80 }

  // Now we calculate the difference between the two.
  var point3 = point2 - point1;
  console.log(point3); // { x: 30, y: 60 }

  // Create yet another point, with a numeric value added to point3:
  var point4 = point3 + 30;
  console.log(point4); // { x: 60, y: 90 }

  // How about a third of that?
  var point5 = point4 / 3;
  console.log(point5); // { x: 20, y: 30 }

  // Multiplying two points with each other multiplies each 
  // coordinate seperately
  var point6 = point5 * new Point(3, 2);
  console.log(point6); // { x: 60, y: 60 }

  var point7 = new Point(10, 20);
  var point8 = point7 + { x: 100, y: 100 };
  console.log(point8); // { x: 110, y: 120 }

  // Adding size objects to points work too,
  // forcing them to be converted to a point first
  var point9 = point8 + new Size(50, 100);
  console.log(point9); // { x: 160, y: 220 }

  // And using the object notation for size works just as well:
  var point10 = point9 + { width: 40, height: 80 };
  console.log(point10); // { x: 200, y: 300 }

  // How about adding a point in array notation instead?
  var point5 = point10 + [100, 0];
  console.log(point5); // { x: 300, y: 300 }
</script>
</head>
<body>
  <canvas id="myCanvas" resize></canvas>
</body>
</html>