开发者

Can I define custom operator overloads in Javascript? [duplicate]

This question already has answers here: Javascript: operator overloading (9 answers) Overloading Arithmetic Operators in JavaScript? (11 answers) Closed 7 years ago.

Is it possible to define custom operators between instances of a type in JavaScript?

For example, given that I have a custom vector class, is it possible to use

vect1 == vect2

to check for equality, whilst the underlying code would be something like this?

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

(This is nonsense of 开发者_JS百科course.)


I agree that the equal function on the vector prototype is the best solution. Note that you can also build other infix-like operators via chaining.

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;
}

You can see online sample here.

Update: Here's a more extensive sample of creating a Factory function that supports chaining.


No, JavaScript doesn’t support operator overloading. You will need to write a method that does this:

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

Then you can use that method like:

vect1.equalTo(vect2)


The best you can do if you want to stick with the == operator:

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)


No, it's not part of the spec (which doesn't mean that there aren't some hacks).


You can change built-in methods of objects in JavaScript, such as valueOf() method. For any two objects to apply the following operators >, <, <=, >=, -, + JavaScript takes the property valueOf() of each object, so it deals with operators kind of like this: obj1.valueOf() == obj2.valueOf() (this does behind the scenes). You can overwrite the valueOf() method depends on your needs. So for example:

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

So this is not the precise answer for your question, but I think this can be an useful stuff for that kind of issues.


It isn't a direct answer for you question but it's worth to note.

PaperScript is a simple extension of JavaScript that adds support for operator overloading to any object.

It used for for making Vector graphics on top of HTML5 Canvas.

It parse PaperScript to JavaScript on script tag with type="text/paperscript":

<!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>


Here is a simple emulation which tests for equality using the 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]);

For non-strict mode functions the array index (defined in 15.4) named data properties of an arguments object whose numeric name values are less than the number of formal parameters of the corresponding function object initially share their values with the corresponding argument bindings in the function’s execution context. This means that changing the property changes the corresponding value of the argument binding and vice-versa. This correspondence is broken if such a property is deleted and then redefined or if the property is changed into an accessor property. For strict mode functions, the values of the arguments object‘s properties are simply a copy of the arguments passed to the function and there is no dynamic linkage between the property values and the formal parameter values.

References

  • The `arguments` object changes if parameters change

  • Annotated ES5: The Arguments Object

  • Javascript check arguments for zero value

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜