是否可以在JavaScript中的类型实例之间定义自定义运算符?
例如,假设我有自定义矢量类,是否可以使用
vect1 == vect2
检查是否相等,而底层代码是这样的?
operator ==(a, b) {
return a.x == b.x && a.y == b.y && a.z == b.z;
}
(当然这是无稽之谈。)
答案 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>