2011-01-15 9 views
26

È possibile definire operatori personalizzati tra istanze di un tipo in JavaScript?Posso definire overload personalizzati dell'operatore in Javascript?

Ad esempio, dato che ho una classe vettore personalizzato, è possibile utilizzare

vect1 == vect2 

per verificare l'uguaglianza, mentre il codice sottostante sarebbe qualcosa di simile?

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

(Questa è una sciocchezza, naturalmente.)

risposta

9

Sono d'accordo che la funzione uguale sul prototipo vettore è la soluzione migliore. Nota che puoi anche costruire altri operatori simili a infissi tramite il concatenamento.

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

È possibile vedere online sample here.

Aggiornamento: Ecco un esempio più ampio di creazione di un Factory function che supporta il concatenamento.

+1

Recentemente ho scoperto il concatenamento usando JQuery.È molto utile in alcuni casi.Grazie mille per il campione! – pimvdb

8

No, JavaScript non supporta l'overloading degli operatori. Avrete bisogno di scrivere un metodo che fa questo:

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

Quindi è possibile utilizzare tale metodo come:

vect1.equalTo(vect2) 
+0

Sì, al momento ho una funzione anche nel prototipo. Tuttavia, sono abituato a usare == per il controllo di uguaglianza. Ma se non è possibile, allora me ne dimenticherò semplicemente – pimvdb

4

No, non è parte della specifica (che non vuol dire che non ci sono più 't some hacks).

+0

Questo è ben trovato, ma l'operatore == non sembra essere "hackerabile". – pimvdb

+3

Vorrei davvero che questo collegamento funzionasse ancora – jedmao

8

Il meglio che puoi fare se si vuole attaccare con l'operatore ==:

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

Questa è anche una possibilità, ma un po 'brutta per essere onesti. Penso che starò meglio usando una funzione di uguaglianza. – pimvdb

+0

Non è così brutto come potresti pensare, perché potresti già avere una funzione 'toString' sul tuo oggetto per facilitare il debugging. Ma poi di nuovo, ho scritto questa risposta solo perché hai detto che preferisci l'operatore '==' a eq. funzioni. Usa quello che ti piace di più. Saluti! :) – galambalazs

+0

Ho effettivamente una funzione toString, ma per il controllo di uguaglianza è più semplice fare v1.equalsTo (v2) che ricordare di doverlo convertire in String, poiché non è il solito modo di farlo - grazie mille in ogni modo! – pimvdb

1

Ecco una semplice emulazione che verifica l'uguaglianza usando l'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]); 

Per non severe funzioni del modo l'indice di matrice (definito in 15.4) denominate proprietà dei dati di un argomenti oggetto il cui nome numerico i valori sono inferiori al numero di parametri formali dell'oggetto funzione corrispondente inizialmente condividono i loro valori con i collegamenti degli argomenti corrispondenti nel contesto di esecuzione della funzione. Ciò significa che la modifica della proprietà modifica il valore corrispondente del binding dell'argomento e viceversa. Questa corrispondenza è interrotta se tale proprietà viene cancellata e quindi ridefinita o se la proprietà viene modificata in una proprietà accessoria. Per le funzioni in modalità rigorosa, i valori delle proprietà dell'oggetto arguments sono semplicemente una copia degli argomenti passati alla funzione e non esiste alcun collegamento dinamico tra i valori delle proprietà e i valori dei parametri formali.

Riferimenti

0

Non è una risposta diretta per la tua domanda, ma vale la pena notare.

PaperScript è una semplice estensione di JavaScript che aggiunge il supporto per l'overloading dell'operatore a qualsiasi oggetto.

Utilizzato per creare grafica vettoriale su HTML5 Canvas.

Si analizza PaperScript di JavaScript sul tag script con 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

Mi rendo conto di questo è una vecchia risposta - non è sicuro come ciò sia rilevante per la domanda dell'OP? – brandonscript

+0

Anche se questa potrebbe essere una conoscenza utile, questa non risponde in realtà alla domanda. –

3

È possibile modificare i metodi di built-in di oggetti in JavaScript, come ad esempio valueOf() metodo. Per qualsiasi due oggetti applicare i seguenti operatori >, <, <=, >=, -, + JavaScript prende la proprietà valueOf() di ciascun oggetto, quindi si tratta di operatori del tipo di questo tipo: obj1.valueOf() == obj2.valueOf() (questo dietro le quinte). È possibile sovrascrivere il metodo valueOf() in base alle proprie esigenze. Così, per esempio:

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 

Quindi questa non è la risposta esatta per la tua domanda, ma penso che questo può essere un materiale utile per questo tipo di problemi.

Problemi correlati