2011-01-15 10 views
26

Ist es möglich, benutzerdefinierte Operatoren zwischen Instanzen eines Typs in JavaScript zu definieren?Kann ich benutzerdefinierte Operatorüberladungen in Javascript definieren?

Zum Beispiel, da ich eine benutzerdefinierte Vektorklasse haben, ist es möglich,

zu verwenden
vect1 == vect2 

für die Gleichstellung zu überprüfen, während der zugrunde liegende Code wäre dies so etwas wie?

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

(Das ist natürlich Unsinn.)

Antwort

9

Ich bin damit einverstanden, dass die gleiche Funktion auf dem Vektor-Prototyp ist die beste Lösung. Beachten Sie, dass Sie auch andere Infix-ähnliche Operatoren über Verkettung erstellen können.

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

Sie können online sample here sehen.

Update: Hier ist ein umfangreicheres Beispiel für die Erstellung einer Factory function, die Verkettung unterstützt.

+1

Ich habe kürzlich Verkettung mit Hilfe von JQuery entdeckt. Es ist in bestimmten Fällen sehr nützlich. Vielen Dank für die Probe! – pimvdb

8

Nein, JavaScript nicht Betreiber Überlastung unterstützen. Sie müssen ein Verfahren schreiben, das dies tut:

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

Dann können Sie diese Methode, wie verwenden:

vect1.equalTo(vect2) 
+0

Ja, ich habe derzeit auch eine Funktion im Prototyp. Allerdings verwende ich == für die Überprüfung der Gleichheit. Aber wenn es nicht möglich ist, dann werde ich es einfach vergessen – pimvdb

4

Nein, es ist nicht Teil der Spezifikation (was nicht bedeutet, dass es aren 't some hacks).

+0

Das ist schön gefunden, aber der Operator == scheint nicht "hackable" zu sein. – pimvdb

+3

Ich wünschte wirklich, dieser Link funktionierte noch – jedmao

8

Das Beste, was Sie tun können, wenn Sie mit dem == Betreiber haften mögen:

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) 
+0

Das ist auch eine Möglichkeit, aber ein bisschen hässlich um ehrlich zu sein. Ich denke, ich werde besser eine Gleichheitsfunktion verwenden. – pimvdb

+0

Es ist nicht so hässlich, wie Sie vielleicht denken, weil Sie möglicherweise bereits eine 'toString'-Funktion auf Ihrem Objekt haben, um das Debuggen zu erleichtern. Aber dann habe ich diese Antwort geschrieben, nur weil du gesagt hast, du bevorzugst den Operator '==. Funktionen. Verwenden Sie, was Ihnen am besten gefällt. Prost! :) – galambalazs

+0

Ich habe tatsächlich eine toString-Funktion, aber für die Überprüfung der Gleichheit ist es einfacher, v1.equalsTo (v2) als Erinnerung daran zu tun, dass Sie es in einen String konvertieren müssen, da dies nicht der übliche Weg ist - vielen Dank Sowieso! – pimvdb

1

Hier ist eine einfache Emulation, die für Gleichheit prüft die guard operator mit:

Für Nicht-Strict-Modus dient dazu, den Array-Index (definiert in 15.4) benannte Daten Eigenschaften eines arguments-Objekt, dessen numerischen Namen

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]); 
Werte sind kleiner als die Anzahl der Formalparameter des entsprechenden Funktionsobjekts, die ihre Werte zunächst mit den entsprechenden Argumentbindungen im Ausführungskontext der Funktion teilen. Dies bedeutet, dass das Ändern der Eigenschaft den entsprechenden Wert der Argumentbindung ändert und umgekehrt. Diese Korrespondenz wird unterbrochen, wenn eine solche Eigenschaft gelöscht und dann neu definiert wird oder wenn die Eigenschaft in eine Accessor-Eigenschaft geändert wird. Für strikte Modusfunktionen sind die Werte der Eigenschaften des arguments-Objekts einfach eine Kopie der Argumente, die an die Funktion übergeben werden, und es gibt keine dynamische Verknüpfung zwischen den Eigenschaftswerten und den formalen Parameterwerten.

Referenzen

0

Es ist keine direkte Antwort für Sie Frage, aber es ist es wert zu beachten.

PaperScript ist eine einfache Erweiterung von JavaScript, die das Überladen von Operatoren für jedes Objekt unterstützt.

Es wurde für die Erstellung von Vektorgrafiken auf HTML5 Canvas verwendet.

Es analysiert PaperScript zu JavaScript auf Script-Tag mit 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> 
+0

Ich realisiere dies ist eine alte Antwort - nicht sicher, wie dies für die Frage des OP obwohl relevant ist? – brandonscript

+0

Während dies nützliches Wissen sein könnte, beantwortet dies nicht wirklich die Frage. –

3

Sie können integrierte Methoden von Objekten in JavaScript ändern, wie valueOf() Verfahren. Für zwei Objekte, die die folgenden Operatoren anwenden können: >, <, <=, >=, -, + JavaScript nimmt die Eigenschaft valueOf() jedes Objekts, also behandelt es Operatoren wie folgt: obj1.valueOf() == obj2.valueOf() (dies tut hinter den Kulissen). Sie können die valueOf() Methode je nach Ihren Bedürfnissen überschreiben. So zum Beispiel:

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 

Das ist also nicht die genaue Antwort auf Ihre Frage, aber ich denke, das ist ein nützliches Material für diese Art von Fragen sein kann.

Verwandte Themen