2011-04-11 10 views
7

Tengo una clase de JavaScript personalizada (creada usando John Resig's Simple Javascript Inheritance). Quiero poder comparar dos instancias de esta clase, usando los símbolos ==, <, >, >= y <=.Anula el comportamiento predeterminado de los operadores de comparación en JavaScript

¿Cómo anulo los comparadores de mi clase personalizada?

+0

En Javascript, '=' no es un comparador, es el operador de asignación. –

+0

Vaya, error ortográfico. Gracias por atraparlo – Chetan

+1

Eche un vistazo a la parte inferior del artículo: * "Este tema será discutido en profundidad en mi libro de trabajo en progreso: Secretos de JavaScript Ninja. Se lanzará en otoño de 2008." * - aún inédito, el libro de Resig es Duke Nukem Forever of JavaScript ':)' –

Respuesta

3

esto no se puede hacer de la manera en que usted está sugiriendo que debería hacerse (aunque eso sería bueno). La mejor manera que he visto este hecho es poner en práctica en el prototipo de un conjunto de métodos para actuar como comparativos:

gte : function(obj){ // greater than or equal 
    // return custom comparison with this as the object comparable on the left 
}, 
gt : function(obj){...}, // greater than but not equal 
eq : function(obj){...}, // equal to 
// etc. 

estaba pensando en este problema somemore hoy en el trabajo y no hay una forma alternativa para aprovechar los operadores de comparación estándar, pero tienen comparaciones de objetos personalizados. El truco sería tener una propiedad (getter) en el objeto que representa el estado comparable. Esto requeriría que todas las instancias del objeto se evalúen con el mismo valor numérico dadas las mismas propiedades comparables. Como ejemplo vamos a hablar vectores:

function Vector(x,y,z){ 
    this.comp = function(){ 
    // assuming these are floats you may wish to create a comparable level of 
    // precision. But this gets the point across. 
    return x + (y * 10) + (z * 100); 
    } 
} 

entonces cuando se configura vectores:

var v1 = new Vector(1,1,1); 
var v2 = new Vector(1,0,1); 
v1.comp() > v2.comp() // true 

esto sólo funciona, por supuesto, si se trata de objetos que pueden dividirse en simples expresión numérica del valor , pero lo positivo es que el código de implementación para obtener el efecto básico es bastante bajo e incluso se puede llegar a hacer que el objeto sea una función que devuelve la expresión numérica de sus componentes.

function Vector(x,y,z){ 
    var v = function v(){ 
    return v.x + (v.y * 10) + (v.z * 100); 
    } 
    v.x = x; 
    v.y = y; 
    v.z = z; 
    return v; 
} 

ahora tiene todos los beneficios del objeto con comparaciones numéricas fáciles y es incluso un poco escueto.

+0

Lo sospechaba tanto:/Gracias de todos modos. – Chetan

+0

Hace un tiempo vi una forma hacky de lograr la sobrecarga del operador en Javascript: http://blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx Siempre quise probarlo y ver si podía mejorarlo, pero nunca lo he hecho. –

+0

@PeterOlson ese enlace ya no funciona. Me gustaría leer sobre eso, si alguna vez lo encuentra, ¿volvería a publicarlo? Gracias. – Gabriel

8

Intenta anular valueOf(). A continuación, puede escribir cosas como esta:

if (obj1.valueOf() === obj2.valueOf()) 
if (obj1.valueOf() < obj2.valueOf()) 
if (obj1.valueOf() > obj2.valueOf()) 

Así que cada vez que necesito un tipo especial de objeto JavaScript para anular la comparación Acabo de añadir valueOf al prototipo. Funciona muy bien para los tipos primitivos, ya que valueOf simplemente devuelve el valor.

Solo ten cuidado con los nulos.

+2

Lo bueno de valueOf es que no necesita llamarlo explícitamente obj1> obj2 llamará valueOf por usted. Al ordenar matrices, a veces se llama a toString (en FF) así que impleméntalo también. – HMR

3

Lee es correcto, si implementa valueOf al comparar objetos (no con === o! ===) esto se usará, pero también deberá usar toString porque se usa al ordenar matrices para algunos razón.

function Test(value){ 
    this.value=value; 
} 
Test.prototype.toString=function(){ 
    console.log("tostring called"); 
    // could do something with case sensitiveness here 
    return new String(this.valueOf()); 
} 
Test.prototype.valueOf=function(){ 
    console.log("valueof called"); 
    return this.value; 
} 

var t1=new Test(11); 
var t2=new Test(1.1); 
var arr=[t1,t2]; 
console.log(arr.sort()); 
console.log(t1>=t2); 
Cuestiones relacionadas