2012-05-10 14 views
21

Czy można zastąpić porównanie równoważności w JavaScript?Zastępowanie porównania równoważności w JavaScript

Najbliższym rozwiązaniem jest zdefiniowanie funkcji valueOf i wywołanie valueOf z plusem przed obiektem.

To działa.

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

Ale to się nie udaje.

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

Oto moje przypadki testowe.

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 tutaj: http://jsfiddle.net/tWyHg/5/

+0

Co dokładnie ty próbujesz osiągnąć tutaj? –

+0

@ ElliotBonneville Tworzę obiekty ułamkowe w javascript. –

+0

Jak wyglądają obiekty ułamkowe? Czy możemy zobaczyć przykładowy wkład? A może po prostu nie rozumiem, co próbujesz zrobić ... –

Odpowiedz

16

To dlatego, że operator == nie porównuje tylko prymitywów, dlatego nie wywołać funkcję valueOf(). Inne używane przez ciebie operatory działają tylko z prymitywami. Obawiam się, że nie można tego osiągnąć w JavaScript. Zobacz http://www.2ality.com/2011/12/fake-operator-overloading.html po więcej szczegółów.

+0

'==' wywołuje ToPrymitive, który wywołuje valueOf ** jeśli ** jedna strona '==' jest nonobject – Pacerier

10

Piggybacking na @Corkscreewe:

To dlatego, że masz do czynienia z obiektami i operatorzy równoważności są tylko będzie porównać czy dwie zmienne odwołują się do tego samego obiektu, a nie, czy dwa obiekty są w jakiś sposób równy.

Jednym z rozwiązań jest użycie "+" przed zmiennymi i zdefiniowanie metody ValueOf dla obiektów. Wywołuje to metodę valueOf dla każdego obiektu, aby "rzutować" jego wartość na liczbę. Znalazłeś to już, ale z pozoru nie wydajesz się z tego bardzo zadowolony.

Bardziej wyrazistym rozwiązaniem może być zdefiniowanie równej funkcji obiektów. Twoje przykłady powyżej:

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 

wiem, że to nie robi dokładnie to, co chcesz (przedefiniować samych operatorów równoważności), ale miejmy nadzieję, że Ci trochę bliżej.

+0

Care że 'NaN === NaN' jest fałszywe. – Pacerier

2

Jeśli szukasz pełnego obiektu, którego szukasz, możesz użyć czegoś podobnego do tego.

/* 
    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; 
} 
Powiązane problemy