Anular la comparación de Equivalencia en Javascript


¿Es posible anular la comparación de equivalencia en Javascript?

Lo más cerca que he llegado a una solución es definiendo la función valueOf e invocando valueOf con un plus delante del objeto.

Esto funciona.

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

Pero esto falla.

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

Aquí están mis casos de prueba.

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

Author: Larry Battle, 2012-05-10

4 answers

Esto se debe a que el operador == no compara solo primitivas, por lo tanto no llama a la función valueOf(). Otros operadores que utilizaste funcionan solo con primitivas. Me temo que no se puede lograr tal cosa en Javascript. Véase http://www.2ality.com/2011/12/fake-operator-overloading.html para más detalles.

 19
Author: Corkscreewe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-28 14:12:36

Piggybacking en @ Corkscreewe:

Esto se debe a que está tratando con Objetos y los operadores de equivalencia solo van a comparar si dos variables hacen referencia al mismo Objeto, no si los dos objetos son de alguna manera iguales.

Una solución es usar "+" delante de las variables y definir un método valueOf para los objetos. Esto llama al método valueOf de cada objeto a "convertir" su valor a un Número. Usted ya ha encontrado esto, pero comprensiblemente no parecen muy satisfecho con él.

Una solución más expresiva podría ser definir una función igual para sus objetos. Usando los ejemplos anteriores:

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

Sé que esto no hace exactamente lo que quieres (redefine los operadores de equivalencia en sí mismos), pero espero que te acerque un poco más.

 11
Author: Noah Freitas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-10 19:07:01

Si está buscando una comparación de objetos completa, es posible que desee usar algo similar a esto.

/*
    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;
}
 2
Author: CBusBus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-10 19:15:53
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;
}
 2
Author: Khalid Azam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-01 18:51:28