2012-05-10 17 views
21

È possibile sovrascrivere il confronto di equivalenza in Javascript?Ignora il confronto di equivalenza in Javascript

La soluzione più vicina a una soluzione è definire la funzione valueOf e richiamare valueOf con un vantaggio davanti all'oggetto.

Questo funziona.

equal(+x == +y, true); 

Ma questo fallisce.

equal(x == y, true, "why does this fail."); 

Ecco i casi di test.

var Obj = function (val) { 
    this.value = val; 
}; 
Obj.prototype.toString = function() { 
    return this.value; 
}; 
Obj.prototype.valueOf = function() { 
    return this.value; 
}; 
var x = new Obj(42); 
var y = new Obj(42); 
var z = new Obj(10); 
test("Comparing custom objects", function() { 
    equal(x >= y, true); 
    equal(x <= y, true); 
    equal(x >= z, true); 
    equal(y >= z, true); 
    equal(x.toString(), y.toString()); 
    equal(+x == +y, true); 
    equal(x == y, true, "why does this fails."); 
}); 

Demo qui: http://jsfiddle.net/tWyHg/5/

+0

Che cosa stai cercando di realizzare qui? –

+0

@ElliotBonneville Sto creando oggetti frazione in javascript. –

+0

Che aspetto hanno gli oggetti della frazione? Possiamo vedere qualche esempio di input? O forse sto solo fraintendendo quello che stai cercando di fare ... –

risposta

16

Questo è perché l'operatore == non confronta solo i primitivi, quindi non chiama la funzione valueOf(). Gli altri operatori che hai usato funzionano solo con le primitive. Temo che tu non possa ottenere una cosa del genere in Javascript. Vedi http://www.2ality.com/2011/12/fake-operator-overloading.html per ulteriori dettagli.

+0

'==' chiama ToPrimitive che chiama valueOf ** if ** un lato di '==' è nonobject – Pacerier

10

Portare in dono @Corkscreewe:

Questo è perché avete a che fare con gli oggetti e gli operatori di equivalenza sono solo andando a confrontare se due variabili fanno riferimento allo stesso oggetto, non è se i due oggetti sono in qualche modo uguali.

Una soluzione è utilizzare "+" davanti alle variabili e definire un metodo valueOf per gli oggetti. Questo chiama il metodo valueOf su ogni oggetto per "castare" il suo valore su un numero. Hai già trovato questo, ma comprensibilmente non mi sembra molto soddisfatto.

Una soluzione più espressiva potrebbe essere quella di definire una funzione di uguale per i propri oggetti. Usando le esempi precedenti:

Obj.prototype.equals = function (o) { 
    return this.valueOf() === o.valueOf(); 
}; 

var x = new Obj(42); 
var y = new Obj(42); 
var z = new Obj(10); 

x.equals(y); // true 
x.equals(z); // false 

So che questo non fa esattamente quello che vuoi (ridefinire gli operatori di equivalenza stessi), ma si spera che si arriva un po 'più vicino.

+0

Care che 'NaN === NaN' è falso. – Pacerier

2

Se è il confronto di oggetti completi che stai cercando, potresti voler usare qualcosa di simile a questo.

/* 
    Object.equals 

    Desc:  Compares an object's properties with another's, return true if the objects 
       are identical. 
    params: 
     obj = Object for comparison 
*/ 
Object.prototype.equals = function(obj) 
{ 

    /*Make sure the object is of the same type as this*/ 
    if(typeof obj != typeof this) 
     return false; 

    /*Iterate through the properties of this object looking for a discrepancy between this and obj*/ 
    for(var property in this) 
    { 

     /*Return false if obj doesn't have the property or if its value doesn't match this' value*/ 
     if(typeof obj[property] == "undefined") 
      return false; 
     if(obj[property] != this[property]) 
      return false; 
    } 

    /*Object's properties are equivalent */ 
    return true; 
} 
1
you can use Es6 Object.is() function to check the property of object. 

Object.prototype.equals = function(obj) 
{ 
    if(typeof obj != "Object") 
     return false; 
    for(var property in this) 
    { 
     if(!Object.is(obj[property], this[property])) 
      return false; 
    } 
    return true; 
} 
Problemi correlati