entre - ¿En qué se diferencian los operadores de comparación de igualdad PHP(== doble igual) e identidad(=== triple igual)?
php si no es igual (19)
¿Cuál es la diferencia entre ==
y ===
?
- ¿Cómo funciona exactamente la comparación vaga
==
? - ¿Cómo funciona exactamente la estricta
===
comparación?
¿Cuáles serían algunos ejemplos útiles?
Las variables tienen un tipo y un valor.
- $ var = "prueba" es una cadena que contiene "prueba"
- $ var2 = 24 es un valor entero cuyo valor es 24.
Cuando usa estas variables (en PHP), a veces no tiene el tipo correcto. Por ejemplo, si lo haces
if ($var == 1) {... do something ...}
PHP tiene que convertir ("para emitir") $ var en entero. En este caso, "$ var == 1" es verdadero porque cualquier cadena no vacía se convierte a 1.
Al usar ===, comprueba que el valor Y EL TIPO son iguales, por lo que "$ var === 1" es falso.
Esto es útil, por ejemplo, cuando tienes una función que puede devolver falso (en caso de error) y 0 (resultado):
if(myFunction() == false) { ... error on myFunction ... }
Este código es incorrecto, como si myFunction()
devuelve 0, se convierte en falso y parece que tiene un error. El código correcto es:
if(myFunction() === false) { ... error on myFunction ... }
porque la prueba es que el valor de retorno "es un booleano y es falso" y no "se puede convertir en falso".
Utilizaría === para probar si una función o variable es falsa en lugar de simplemente equiparar a falso (cero o una cadena vacía).
$needle = ''a'';
$haystack = ''abc'';
$pos = strpos($haystack, $needle);
if ($pos === false) {
echo $needle . '' was not found in '' . $haystack;
} else {
echo $needle . '' was found in '' . $haystack . '' at location '' . $pos;
}
En este caso strpos devolvería 0 que equivaldría a falso en la prueba
if ($pos == false)
o
if (!$pos)
que no es lo que quieres aquí.
Dado x = 5
1) Operador: == es "igual a". x == 8
es falso
2) Operador: === es "exactamente igual a" (valor y tipo) x === 5
es verdadero, x === "5"
es falso
Una adición a las otras respuestas relativas a la comparación de objetos:
== compara objetos usando el nombre del objeto y sus valores. Si dos objetos son del mismo tipo y tienen los mismos valores de miembro, $a == $b
da como verdadero.
=== compara el id del objeto interno de los objetos. Incluso si los miembros son iguales, $a !== $b
si no son exactamente el mismo objeto.
class TestClassA {
public $a;
}
class TestClassB {
public $a;
}
$a1 = new TestClassA();
$a2 = new TestClassA();
$b = new TestClassB();
$a1->a = 10;
$a2->a = 10;
$b->a = 10;
$a1 == $a1;
$a1 == $a2; // Same members
$a1 != $b; // Different classes
$a1 === $a1;
$a1 !== $a2; // Not the same object
$a = 5; // 5 as an integer
var_dump($a == 5); // compare value; return true
var_dump($a == ''5''); // compare value (ignore type); return true
var_dump($a === 5); // compare type/value (integer vs. integer); return true
var_dump($a === ''5''); // compare type/value (integer vs. string); return false
Ten cuidado, sin embargo. Aquí hay un problema notorio.
// ''test'' is found at position 0, which is interpreted as the boolean ''false''
if (strpos(''testing'', ''test'')) {
// code...
}
vs.
// true, as strict comparison was made (0 !== false)
if (strpos(''testing'', ''test'') !== false) {
// code...
}
En los términos más simples:
== verifica si es equivalente (solo valor)
=== comprueba si es el mismo (valor && tipo)
Equivalente vs. Igual: una analogía
1 + 1 = 2 + 0 (equivalente)
1 + 1 = 1 + 1 (lo mismo)
En PHP:
verdadero == 1 (verdadero - equivalente en valor)
verdadero === 1 (falso - no es lo mismo en valor && tipo)
- true es booleano
- 1 es int
En cuanto a cuándo usar uno sobre el otro, tome por ejemplo la función fwrite()
en PHP.
Esta función escribe contenido en una secuencia de archivos. Según PHP, " fwrite()
devuelve el número de bytes escritos, o FALSE en caso de error". Si desea probar si la llamada a la función fue exitosa, este método es defectuoso:
if (!fwrite(stuff))
{
log(''error!'');
}
Puede devolver cero (y se considera exitoso), y su condición aún se activa. El camino correcto sería:
if (fwrite(stuff) === FALSE)
{
log(''error!'');
}
En lo que respecta a JavaScript:
El operador === funciona igual que el operador ==, pero requiere que sus operandos tengan no solo el mismo valor, sino también el mismo tipo de datos.
Por ejemplo, el ejemplo siguiente mostrará ''xey son iguales'', pero no ''xey son idénticos''.
var x = 4;
var y = ''4'';
if (x == y) {
alert(''x and y are equal'');
}
if (x === y) {
alert(''x and y are identical'');
}
En resumen, === funciona de la misma manera que == en la mayoría de los otros lenguajes de programación.
PHP le permite hacer comparaciones que realmente no tienen sentido. Ejemplo:
$y = "wauv";
$x = false;
if ($x == $y)
...
Si bien esto permite algunos "accesos directos" interesantes, debe tener cuidado ya que una función que devuelve algo que no debería (como "error" en lugar de un número) no quedará atrapada, y usted se preguntará qué sucedió.
En PHP, == compara valores y realiza la conversión de tipo si es necesario (por ejemplo, la cadena "12343sdfjskfjds" se convertirá en "12343" en una comparación entera). === comparará el valor Y el tipo y devolverá falso si el tipo no es el mismo.
Si miras el manual de PHP, verás que muchas funciones devuelven "falso" si la función falla, pero pueden devolver 0 en un escenario exitoso, por lo que recomiendan hacer "if (function ()! == falso) "para evitar errores.
Se supone que el operador ===
compara la igualdad exacta de contenido mientras que el operador ==
compararía la igualdad semántica. En particular, forzará cadenas de números.
La igualdad es un vasto tema. Vea el artículo de Wikipedia sobre igualdad .
Se trata de tipos de datos. Tome un BOOL
(verdadero o falso) por ejemplo:
true
también es igual a 1
y false
también es igual a 0
El ==
no se preocupa por los tipos de datos cuando compara: Entonces, si tenía una variable que es 1 (que también podría ser true
):
$var=1;
Y luego compare con el ==
:
if ($var == true)
{
echo"var is true";
}
Pero $var
realidad no es igual a true
, ¿verdad? Tiene el valor int de 1
lugar, que a su vez es igual a verdadero.
Con ===
, los tipos de datos se verifican para asegurarse de que las dos variables / objetos / lo que sea estén usando el mismo tipo.
Entonces si lo hice
if ($var === true)
{
echo "var is true";
}
esa condición no sería cierta, ya que $var !== true
solo == true
(si sabes a qué me refiero).
Por qué necesitarías esto?
Simple - echemos un vistazo a una de las funciones de PHP: array_search()
:
La función array_search()
simplemente busca un valor en una matriz y devuelve la clave del elemento en el que se encontró el valor. Si no se pudo encontrar el valor en la matriz, devuelve falso . Pero, ¿qué array_search()
si hiciera un array_search()
en un valor que estaba almacenado en el primer elemento de la matriz (que tendría la clave de matriz de 0
) ... la función array_search()
devolvería 0 ... que es igual a falso ...
Entonces si lo hiciste:
$arr = array("name");
if (array_search("name", $arr) == false)
{
// This would return 0 (the key of the element the val was found
// in), but because we''re using ==, we''ll think the function
// actually returned false...when it didn''t.
}
Entonces, ¿ves cómo esto podría ser un problema ahora?
La mayoría de las personas no usan == false
al verificar si una función devuelve falso. En cambio, usan el !
. Pero en realidad, esto es exactamente lo mismo que usar ==false
, así que si lo hiciste:
$arr = array("name");
if (!array_search("name", $arr)) // This is the same as doing (array_search("name", $arr) == false)
Entonces, para cosas como esas, usaría el ===
lugar, para que el tipo de datos esté marcado.
Un ejemplo es que un atributo de base de datos puede ser nulo o "":
$attributeFromArray = "";
if ($attributeFromArray == ""){} //true
if ($attributeFromArray === ""){} //true
if ($attributeFromArray == null){} //true
if ($attributeFromArray === null){} //false
$attributeFromArray = null;
if ($attributeFromArray == ""){} //true
if ($attributeFromArray === ""){} //false
if ($attributeFromArray == null){} //true
if ($attributeFromArray === null){} //true
<?php
/**
* Comparison of two PHP objects == ===
* Checks for
* 1. References yes yes
* 2. Instances with matching attributes and its values yes no
* 3. Instances with different attributes yes no
**/
// There is no need to worry about comparing visibility of property or
// method, because it will be the same whenever an object instance is
// created, however visibility of an object can be modified during run
// time using ReflectionClass()
// http://php.net/manual/en/reflectionproperty.setaccessible.php
//
class Foo
{
public $foobar = 1;
public function createNewProperty($name, $value)
{
$this->{$name} = $value;
}
}
class Bar
{
}
// 1. Object handles or references
// Is an object a reference to itself or a clone or totally a different object?
//
// == true Name of two objects are same, for example, Foo() and Foo()
// == false Name of two objects are different, for example, Foo() and Bar()
// === true ID of two objects are same, for example, 1 and 1
// === false ID of two objects are different, for example, 1 and 2
echo "1. Object handles or references (both == and ===) <br />";
$bar = new Foo(); // New object Foo() created
$bar2 = new Foo(); // New object Foo() created
$baz = clone $bar; // Object Foo() cloned
$qux = $bar; // Object Foo() referenced
$norf = new Bar(); // New object Bar() created
echo "bar";
var_dump($bar);
echo "baz";
var_dump($baz);
echo "qux";
var_dump($qux);
echo "bar2";
var_dump($bar2);
echo "norf";
var_dump($norf);
// Clone: == true and === false
echo ''$bar == $bar2'';
var_dump($bar == $bar2); // true
echo ''$bar === $bar2'';
var_dump($bar === $bar2); // false
echo ''$bar == $baz'';
var_dump($bar == $baz); // true
echo ''$bar === $baz'';
var_dump($bar === $baz); // false
// Object reference: == true and === true
echo ''$bar == $qux'';
var_dump($bar == $qux); // true
echo ''$bar === $qux'';
var_dump($bar === $qux); // true
// Two different objects: == false and === false
echo ''$bar == $norf'';
var_dump($bar == $norf); // false
echo ''$bar === $norf'';
var_dump($bar === $norf); // false
// 2. Instances with matching attributes and its values (only ==).
// What happens when objects (even in cloned object) have same
// attributes but varying values?
// $foobar value is different
echo "2. Instances with matching attributes and its values (only ==) <br />";
$baz->foobar = 2;
echo ''$foobar'' . " value is different <br />";
echo ''$bar->foobar = '' . $bar->foobar . "<br />";
echo ''$baz->foobar = '' . $baz->foobar . "<br />";
echo ''$bar == $baz'';
var_dump($bar == $baz); // false
// $foobar''s value is the same again
$baz->foobar = 1;
echo ''$foobar'' . " value is the same again <br />";
echo ''$bar->foobar is '' . $bar->foobar . "<br />";
echo ''$baz->foobar is '' . $baz->foobar . "<br />";
echo ''$bar == $baz'';
var_dump($bar == $baz); // true
// Changing values of properties in $qux object will change the property
// value of $bar and evaluates true always, because $qux = &$bar.
$qux->foobar = 2;
echo ''$foobar value of both $qux and $bar is 2, because $qux = &$bar'' . "<br />";
echo ''$qux->foobar is '' . $qux->foobar . "<br />";
echo ''$bar->foobar is '' . $bar->foobar . "<br />";
echo ''$bar == $qux'';
var_dump($bar == $qux); // true
// 3. Instances with different attributes (only ==)
// What happens when objects have different attributes even though
// one of the attributes has same value?
echo "3. Instances with different attributes (only ==) <br />";
// Dynamically create a property with the name in $name and value
// in $value for baz object
$name = ''newproperty'';
$value = null;
$baz->createNewProperty($name, $value);
echo ''$baz->newproperty is '' . $baz->{$name};
var_dump($baz);
$baz->foobar = 2;
echo ''$foobar'' . " value is same again <br />";
echo ''$bar->foobar is '' . $bar->foobar . "<br />";
echo ''$baz->foobar is '' . $baz->foobar . "<br />";
echo ''$bar == $baz'';
var_dump($bar == $baz); // false
var_dump($bar);
var_dump($baz);
?>
PHP es un lenguaje poco tipado. Usar el operador de doble igual permite una verificación suelta de una variable.
Si se verifica sin apretar un valor, se permitiría que algunos valores similares, pero no iguales, se equiparen como el mismo:
- ''''
- nulo
- falso
- 0
Todos estos valores se igualarían como iguales usando el operador de doble igualdad.
Diferencia entre ==
y ===
La diferencia entre el operador igual ==
igual y el operador estricto ===
idéntico se explica exactamente en el manual :
Operadores de comparación
┌──────────┬───────────┬───────────────────────────────────────────────────────────┐ │ Example │ Name │ Result │ ├──────────┼───────────┼───────────────────────────────────────────────────────────┤ │$a == $b │ Equal │ TRUE if $a is equal to $b after type juggling. │ │$a === $b │ Identical │ TRUE if $a is equal to $b, and they are of the same type. │ └──────────┴───────────┴───────────────────────────────────────────────────────────┘
Sin apretar ==
igual comparación
Si está usando el operador ==
, o cualquier otro operador de comparación que use una comparación aproximada como !=
, <>
O ==
, siempre debe mirar el contexto para ver qué, dónde y por qué algo se convierte para entender qué está pasando.
Conversión de reglas
- Convertir a booleano
- Conversión a entero
- Convertir a flotar
- Convertir a cadena
- Conversión a matriz
- Convertir a objeto
- Convertir a recurso
- Convertir a NULL
Tipo tabla de comparación
Como referencia y ejemplo, puede ver la tabla de comparación en el manual :
Comparaciones sueltas con
==
┌─────────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┐ │ │ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ array() │ "php" │ "" │ ├─────────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼─────────┼───────┼───────┤ │ TRUE │ TRUE │ FALSE │ TRUE │ FALSE │ TRUE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ │ FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ TRUE │ FALSE │ TRUE │ │ 1 │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ 0 │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ TRUE │ TRUE │ │ -1 │ TRUE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "1" │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "0" │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "-1" │ TRUE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ │ NULL │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ TRUE │ FALSE │ TRUE │ │ array() │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ TRUE │ FALSE │ FALSE │ │ "php" │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ │ "" │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ └─────────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┘
Estricto ===
comparación idéntica
Si está utilizando el operador ===
o cualquier otro operador de comparación que use una comparación estricta como !==
o ===
, entonces siempre puede estar seguro de que los tipos no cambiarán mágicamente , porque no habrá conversión. pasando. Entonces, con una comparación estricta, el tipo y el valor tienen que ser iguales, no solo el valor.
Tipo tabla de comparación
Como referencia y ejemplo, puede ver la tabla de comparación en el manual :
Estrictas comparaciones con
===
┌─────────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┐ │ │ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ array() │ "php" │ "" │ ├─────────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼─────────┼───────┼───────┤ │ TRUE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ 1 │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ 0 │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ -1 │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "1" │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "0" │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "-1" │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ │ NULL │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ │ array() │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ │ "php" │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ │ "" │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ └─────────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┘
Pocos de los ejemplos
var_dump(5 == 5); // True
var_dump(5 == "5"); // True because == checks only same value not type
var_dump(5 === 5); // True
var_dump(5 === "5"); // False because value are same but data type are different.
PD
== Compara solo el valor, no molestará sobre los tipos de datos
vs.
=== Compara los valores y tipos de datos
Una imagen vale mas que mil palabras:
PHP Double Equals ==
tabla de igualdad:
PHP Triple Equals ===
Tabla de igualdad:
Código fuente para crear estas imágenes:
https://github.com/sentientmachine/php_equality_charts
Meditación Gurú
Aquellos que desean mantener su cordura, no lean más.
- ''=='' convierte operandos izquierdos y derechos a números cuando sea posible (123 == "123foo", pero "123"! = "123foo"
- Una cadena hexagonal entre comillas ocasionalmente es un flotador y se le lanzará contra tu voluntad.
- == no es transitivo porque ("0" es == a 0, y 0 es == a "" pero "0"! = "")
- "6" == "6", "4.2" == "4.20" y "133" == "0133". Pero 133! = 0133, porque 0133 es octal. Pero "0x10" == "16" y "1e3" == "1000"
Las variables de PHP que aún no se han declarado son falsas.
False es igual a 0, blankstring y array vacío y "0".
- Cuando los números son lo suficientemente grandes, son == Infinito.
NAN no == en sí mismo, pero es Verdadero.
Una clase nueva es == a 1.
- False es el valor más peligroso porque False es == para la mayoría de las otras variables, principalmente para derrotar su propósito.
Esperanza:
Si usa PHP, no usará el operador de doble igual, siempre use triple equals.
El operador == arroja entre dos tipos diferentes si son diferentes, mientras que el operador === realiza una ''comparación de tipo seguro''. Eso significa que solo devolverá verdadero si ambos operandos tienen el mismo tipo y el mismo valor.
Ejemplos:
1 === 1: true
1 == 1: true
1 === "1": false // 1 is an integer, "1" is a string
1 == "1": true // "1" gets casted to an integer, which is 1
"foo" === "foo": true // both operands are strings and have the same value
Advertencia : dos instancias de la misma clase con miembros equivalentes NO coinciden con el operador ===
. Ejemplo:
$a = new stdClass();
$a->foo = "bar";
$b = clone $a;
var_dump($a === $b); // bool(false)
Todas las respuestas hasta ahora ignoran un problema peligroso con ===. Se ha observado de pasada, pero no estresado, que el entero y el doble son tipos diferentes, por lo que el siguiente código:
$n = 1000;
$d = $n + 0.0e0;
echo ''<br/>''. ( ($n == $d)?''equal'' :''not equal'' );
echo ''<br/>''. ( ($n === $d)?''equal'' :''not equal'' );
da:
equal
not equal
Tenga en cuenta que esto NO es un caso de "error de redondeo". Los dos números son exactamente iguales hasta el último bit, pero tienen diferentes tipos.
Este es un problema desagradable porque un programa que usa === puede funcionar felizmente por años si todos los números son lo suficientemente pequeños (donde "lo suficientemente pequeño" depende del hardware y sistema operativo en el que se ejecuta). Sin embargo, si por casualidad, un entero resulta ser lo suficientemente grande como para convertirse en un doble, su tipo se cambia "para siempre", aunque una operación posterior, o muchas operaciones, podría devolverlo a un entero pequeño en valor. Y, empeora. Se puede propagar: la infección de doble se puede transmitir a todo lo que toca, un cálculo a la vez.
En el mundo real, es probable que esto sea un problema en los programas que manejan fechas posteriores al año 2038, por ejemplo. En este momento, las marcas de tiempo de UNIX (número de segundos desde 1970-01-01 00:00:00 UTC) requerirán más de 32 bits, por lo que su representación cambiará "mágicamente" al doble en algunos sistemas. Por lo tanto, si calcula la diferencia entre dos veces, puede terminar con un par de segundos, pero como un resultado doble, en lugar del entero que ocurre en el año 2017.
Creo que esto es mucho peor que las conversiones entre cadenas y números porque es sutil. Me resulta fácil hacer un seguimiento de lo que es una cadena y lo que es un número, pero el seguimiento de la cantidad de bits en un número me supera.
Entonces, en las respuestas anteriores hay algunas buenas tablas, pero ninguna distinción entre 1 (como un entero) y 1 (doble sutil) y 1.0 (doble obvio). Además, los consejos que siempre debes usar === y nunca == no son geniales porque === a veces fallarán donde == funciona correctamente. Además, JavaScript no es equivalente a este respecto porque tiene solo un tipo de número (internamente puede tener diferentes representaciones de bits, pero no causa problemas para ===).
Mi consejo: no uses ninguno. Necesitas escribir tu propia función de comparación para arreglar realmente este desastre.