condicionales - operadores de comparacion javascript




¿Qué operador igual(== vs===) se debe usar en las comparaciones de JavaScript? (20)

Comprueba si los mismos lados son iguales en tipo y valor .

Ejemplo:

'1' === 1 // will return "false" because `string` is not a `number`

Ejemplo común:

0 == ''  // will be "true", but it's very common to want this check to be "false"

Otro ejemplo común:

null == undefined // returns "true", but in most cases a distinction is necessary

Estoy usando JSLint para ir a través de JavaScript, y está devolviendo muchas sugerencias para reemplazar == (dos signos iguales) con === (tres signos iguales) al hacer cosas como comparar idSele_UNVEHtype.value.length == 0 dentro de un if declaración.

¿Hay un beneficio de rendimiento al reemplazar == con === ?

Cualquier mejora en el rendimiento sería bienvenida ya que existen muchos operadores de comparación.

Si no se realiza una conversión de tipo, ¿habría una ganancia de rendimiento superior a == ?


Diagrama de flujo de ejecución de Javascript para igualdad estricta / Comparación '==='

Diagrama de flujo de ejecución de Javascript para igualdad no estricta / comparación '=='


El operador de identidad ( === ) se comporta de manera idéntica al operador de igualdad ( == ), excepto que no se realiza una conversión de tipo, y los tipos deben ser iguales para que se los considere iguales.

Referencia: Javascript Tutorial: Operadores de comparación

El operador == comparará la igualdad después de hacer cualquier conversión de tipo necesaria . El operador === no realizará la conversión, por lo que si dos valores no son del mismo tipo === simplemente devolverá false . Ambos son igualmente rápidos.

Para citar el excelente JavaScript de Douglas Crockford : The Good Parts ,

JavaScript tiene dos conjuntos de operadores de igualdad: === y !== , y sus gemelos malvados == y != . Los buenos funcionan de la manera que usted esperaría. Si los dos operandos son del mismo tipo y tienen el mismo valor, entonces === produce true y !== produce false . Los gemelos malvados hacen lo correcto cuando los operandos son del mismo tipo, pero si son de diferentes tipos, intentan forzar los valores. Las reglas por las que hacen eso son complicadas y no memorables. Estos son algunos de los casos interesantes:

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true

La falta de transitividad es alarmante. Mi consejo es nunca usar a los gemelos malvados. En su lugar, utilice siempre === y !== . Todas las comparaciones que se acaban de mostrar producen false con el operador === .

Actualizar:

@Casebash planteó un buen punto en los comentarios y en la answer @Phillipe Laybaert con respecto a los tipos de referencia. Para los tipos de referencia == y === actúan de manera coherente entre sí (excepto en un caso especial).

var a = [1,2,3];
var b = [1,2,3];

var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };

var e = "text";
var f = "te" + "xt";

a == b            // false
a === b           // false

c == d            // false
c === d           // false

e == f            // true
e === f           // true

El caso especial es cuando se compara un literal con un objeto que se evalúa al mismo literal, debido a su método toString o valueOf . Por ejemplo, considere la comparación de un literal de cadena con un objeto de cadena creado por el constructor de String .

"abc" == new String("abc")    // true
"abc" === new String("abc")   // false

Aquí el operador == está verificando los valores de los dos objetos y devolviendo true , pero el === está viendo que no son del mismo tipo y devolviendo false . ¿Cuál es la correcta? Eso realmente depende de lo que estás tratando de comparar. Mi consejo es que omita la pregunta por completo y simplemente no use el constructor String para crear objetos de cadena.

Referencia
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3


En JavaScript significa del mismo valor y tipo.

Por ejemplo,

4 == "4" // will return true

pero

4 === "4" // will return false 

En las respuestas aquí, no leí nada sobre lo que significa igual . Algunos dirán que === significa igual y del mismo tipo , pero eso no es realmente cierto. En realidad, significa que ambos operandos hacen referencia al mismo objeto o, en el caso de los tipos de valor, tienen el mismo valor .

Entonces, tomemos el siguiente código:

var a = [1,2,3];
var b = [1,2,3];
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Lo mismo aquí:

var a = { x: 1, y: 2 };
var b = { x: 1, y: 2 };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

O incluso:

var a = { };
var b = { };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Este comportamiento no siempre es obvio. Hay más en la historia que ser iguales y ser del mismo tipo.

La regla es:

Para tipos de valor (números):
a === b devuelve true si a y b tienen el mismo valor y son del mismo tipo

Para tipos de referencia:
a === b devuelve true si a y b referencia al mismo objeto exacto

Para cuerdas:
a === b devuelve true si a y b son ambas cadenas y contienen los mismos caracteres exactos

Cuerdas: el caso especial ...

Las cadenas no son tipos de valor, pero en Javascript se comportan como tipos de valor, por lo que serán "iguales" cuando los caracteres en la cadena sean iguales y cuando tengan la misma longitud (como se explica en la tercera regla)

Ahora se vuelve interesante:

var a = "12" + "3";
var b = "123";

alert(a === b); // returns true, because strings behave like value types

Pero ¿qué tal esto ?:

var a = new String("123");
var b = "123";

alert(a === b); // returns false !! (but they are equal and of the same type)

¿Pensé que las cuerdas se comportan como tipos de valor? Bueno, depende de a quién le preguntes ... En este caso, a y b no son del mismo tipo. a es de tipo Object , mientras que b es de tipo string . Solo recuerde que crear un objeto de cadena usando el constructor de String crea algo de tipo Object que se comporta como una cadena la mayor parte del tiempo .


En un script típico no habrá diferencia de rendimiento. Más importante puede ser el hecho de que mil "===" es 1 KB más pesado que mil "==" :) Los perfiladores de JavaScript pueden indicarle si hay una diferencia de rendimiento en su caso.

Pero personalmente haría lo que JSLint sugiere. Esta recomendación no se debe a problemas de rendimiento, sino porque los medios de coacción de tipo ('\t\r\n' == 0) son verdaderos.


Es una prueba de verificación estricta.

Es algo bueno, especialmente si está marcando entre 0 y falso y nulo.

Por ejemplo, si tiene:

$a = 0;

Entonces:

$a==0; 
$a==NULL;
$a==false;

Todas las devoluciones son verdaderas y es posible que no quieras esto. Supongamos que tiene una función que puede devolver el índice 0 de una matriz o falso si falla. Si marca con "==" falso, puede obtener un resultado confuso.

Así que con lo mismo que el anterior, pero una prueba estricta:

$a = 0;

$a===0; // returns true
$a===NULL; // returns false
$a===false; // returns false

JSLint a veces te da razones poco realistas para modificar cosas. === tiene exactamente el mismo rendimiento que == si los tipos ya son iguales.

Es más rápido solo cuando los tipos no son los mismos, en cuyo caso no intenta convertir tipos, sino que devuelve directamente un falso.

Por lo tanto, IMHO, JSLint puede usarse para escribir código nuevo, pero se debe evitar a toda costa la excesiva optimización inútil.

Lo que significa que no hay razón para cambiar ==a ===un cheque, como if (a == 'test')cuando lo sabes por un hecho de que solo puede ser una Cadena.

Modificar una gran cantidad de código de esta manera desperdicia el tiempo de los desarrolladores y revisores y no logra nada.


Permítanme agregar este consejo:

En caso de duda, lea la specification !

ECMA-262 es la especificación para un lenguaje de script del cual JavaScript es un dialecto. Por supuesto, en la práctica importa más cómo se comportan los navegadores más importantes que una definición esotérica de cómo se supone que se maneja algo. Pero es útil entender por qué la nueva cadena ("a")! == "a" .

Permítame explicarle cómo leer la especificación para aclarar esta pregunta. Veo que en este viejo tema nadie tuvo una respuesta para el efecto muy extraño. Entonces, si puedes leer una especificación, esto te ayudará enormemente en tu profesión. Es una habilidad adquirida. Entonces, continuemos.

La búsqueda en el archivo PDF de === me lleva a la página 56 de la especificación: 11.9.4. El Operador de Igualdad Estricta (===) , y después de vadear a través de la especificación, encuentro:

11.9.6 El algoritmo de comparación de igualdad estricta
La comparación x === y, donde x e y son valores, produce verdadero o falso . Tal comparación se realiza de la siguiente manera:
1. Si el Tipo (x) es diferente del Tipo (y), devuelva falso .
2. Si el Tipo (x) no está definido, devuelva verdadero .
3. Si el Tipo (x) es Nulo, devuelva verdadero .
4. Si el Tipo (x) no es Número, vaya al paso 11.
5. Si x es NaN , devuelve falso .
6. Si y es NaN , devuelve falso .
7. Si x es el mismo valor numérico que y, devuelva verdadero .
8. Si x es +0 e y es −0, devuelve verdadero .
9. Si x es −0 e y es +0, devuelve verdadero .
10. Devuelve falso .
11. Si Tipo (x) es Cadena, entonces devuelva verdadero si x e y son exactamente la misma secuencia de caracteres (la misma longitud y los mismos caracteres en las posiciones correspondientes); de lo contrario, devuelve falso .
12. Si el Tipo (x) es Booleano, devuelve verdadero si x e y son verdaderos o ambos falsos ; de lo contrario, devuelve falso .
13. Devuelva verdadero si x e y se refieren al mismo objeto o si se refieren a objetos unidos entre sí (ver 13.1.2). De lo contrario, devuelve falso .

Interesante es el paso 11. Sí, las cadenas se tratan como tipos de valor. Pero esto no explica por qué la nueva cadena ("a")! == "a" . ¿Tenemos un navegador que no se ajusta a ECMA-262?

¡No tan rapido!

Veamos los tipos de los operandos. Pruébelo usted mismo envolviéndolos en typeof () . Encuentro que la nueva Cadena ("a") es un objeto, y se usa el paso 1: devuelva falso si los tipos son diferentes.

Si se pregunta por qué la cadena nueva ("a") no devuelve una cadena, ¿qué le parece un ejercicio de lectura de una especificación? ¡Que te diviertas!

Aidiakapi escribió esto en un comentario a continuación:

De la especificación

11.2.2 El nuevo operador :

Si el Tipo (constructor) no es Objeto, lance una excepción TypeError.

En otras palabras, si String no fuera del tipo Object, no podría usarse con el nuevo operador.

new siempre devuelve un objeto, incluso para constructores de cadenas , también. Y ay! El valor semántico de las cadenas (ver paso 11) se pierde.

Y esto finalmente significa: nueva cadena ("a")! == "a" .


Probé esto en Firefox con Firebug usando un código como este:

console.time("testEquality");
var n = 0;
while(true) {
    n++;
    if(n==100000) 
        break;
}
console.timeEnd("testEquality");

y

console.time("testTypeEquality");
var n = 0;
while(true) {
    n++;
    if(n===100000) 
        break;
}
console.timeEnd("testTypeEquality");

Mis resultados (probados cinco veces cada uno y promediados):

==: 115.2
===: 114.4

Así que diría que la diferencia minúscula (esto es más de 100000 iteraciones, recuerde) es insignificante. El rendimiento no es una razón para hacer === . Escriba seguridad (bueno, tan seguro como lo va a obtener en JavaScript), y la calidad del código es.


Una representación pictórica interesante de la comparación de igualdad entre == y === .

Fuente: dorey.github.io/JavaScript-Equality-Table

var1 === var2

Cuando se usa === para las pruebas de igualdad de JavaScript, todo es como es. Nada se convierte antes de ser evaluado.

var1 == var2

Cuando se utiliza == para las pruebas de igualdad de JavaScript, se producen algunas conversiones funky.

Moraleja de la historia:

Use === menos que entienda completamente las conversiones que tienen lugar con == .


Usando el operador == ( Igualdad )

true == 1; //true, because 'true' is converted to 1 and then compared
"2" == 2;  //true, because "2" is converted to 2 and then compared

Usando el operador === ( Identidad )

true === 1; //false
"2" === 2;  //false

Esto se debe a que el operador de igualdad == hace tipo de coerción , lo que significa que el intérprete intenta de manera implícita convertir los valores antes de comparar.

Por otro lado, el operador de identidad === no realiza coacción de tipo y, por lo tanto, no convierte los valores al comparar.


=== operador === comprueba los valores y los tipos de variables para la igualdad.

== operador == simplemente verifica el valor de las variables para la igualdad.


El operador de comparación igual == es confuso y debe evitarse.

Si TIENE QUE vivir con eso, entonces recuerde las siguientes 3 cosas:

  1. No es transitiva: (a == b) y (b == c) no conduce a (a == c)
  2. Se excluye mutuamente a su negación: (a == b) y (a! = B) siempre tienen valores booleanos opuestos, con todos a y b.
  3. En caso de duda, aprenda de memoria la siguiente tabla de verdad:

MESA DE VERDAD DEL OPERADOR IGUAL EN JAVASCRIPT

  • Cada fila en la tabla es un conjunto de 3 valores mutuamente "iguales", lo que significa que cualquiera de los 2 valores entre ellos son iguales utilizando el signo == igual

** EXTRAÑO: tenga en cuenta que cualquiera de los dos valores en la primera columna no son iguales en ese sentido. **

''       == 0 == false   // Any two values among these 3 ones are equal with the == operator
'0'      == 0 == false   // Also a set of 3 equal values, note that only 0 and false are repeated
'\t'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\r'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\n'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\t\r\n' == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

null == undefined  // These two "default" values are not-equal to any of the listed values above
NaN                // NaN is not equal to any thing, even to itself.

¿Por qué == es tan impredecible?

¿Qué obtienes al comparar una cadena vacía "" con el número cero 0 ?

true

Sí, eso es correcto de acuerdo con == una cadena vacía y el número cero es el mismo tiempo.

Y no termina ahí, aquí hay otro:

'0' == false // true

Las cosas se ponen realmente raras con matrices.

[1] == true // true
[] == false // true
[[]] == false // true
[0] == false // true

Entonces más raro con cuerdas

[1,2,3] == '1,2,3' // true - REALLY?!
'\r\n\t' == 0 // true - Come on!

Se pone peor:

¿Cuándo es igual no es igual?

let A = ''  // empty string
let B = 0   // zero
let C = '0' // zero string

A == B // true - ok... 
B == C // true - so far so good...
A == C // **FALSE** - Plot twist!

Déjame decirlo de nuevo:

(A == B) && (B == C) // true
(A == C) // **FALSE**

Y esto es solo la locura que obtienes con los primitivos.

Es un nuevo nivel de locura cuando usas == con objetos.

En este punto tu probablemente te estás preguntando ...

¿Por qué pasó esto?

Bueno, es porque a diferencia de "triple igual" ( === ) que solo verifica si dos valores son iguales.

== hace un montón de otras cosas .

Tiene manejo especial para funciones, manejo especial para nulos, indefinido, cadenas, lo que sea.

Se pone bastante chiflado.

De hecho, si intentas escribir una función que haga lo que == hace, se vería algo así:

function isEqual(x, y) { // if `==` were a function
    if(typeof y === typeof x) return y === x;
    // treat null and undefined the same
    var xIsNothing = (y === undefined) || (y === null);
    var yIsNothing = (x === undefined) || (x === null);

    if(xIsNothing || yIsNothing) return (xIsNothing && yIsNothing);

    if(typeof y === "function" || typeof x === "function") {
        // if either value is a string 
        // convert the function into a string and compare
        if(typeof x === "string") {
            return x === y.toString();
        } else if(typeof y === "string") {
            return x.toString() === y;
        } 
        return false;
    }

    if(typeof x === "object") x = toPrimitive(x);
    if(typeof y === "object") y = toPrimitive(y);
    if(typeof y === typeof x) return y === x;

    // convert x and y into numbers if they are not already use the "+" trick
    if(typeof x !== "number") x = +x;
    if(typeof y !== "number") y = +y;
    // actually the real `==` is even more complicated than this, especially in ES6
    return x === y;
}

function toPrimitive(obj) {
    var value = obj.valueOf();
    if(obj !== value) return value;
    return obj.toString();
}

Entonces, ¿qué significa esto?

Significa que == es complicado.

Debido a que es complicado, es difícil saber qué sucederá cuando lo uses.

Lo que significa que podría terminar con errores.

Así que la moraleja de la historia es ...

Haz tu vida menos complicada.

Utilice === lugar de == .

El fin.


El problema es que puedes tener problemas fácilmente ya que JavaScript tiene muchas conversiones implícitas, lo que significa ...

var x = 0;
var isTrue = x == null;
var isFalse = x === null;

Que muy pronto se convierte en un problema. La mejor muestra de por qué la conversión implícita es "malvada" se puede tomar de este código en MFC / C ++ que en realidad se compilará debido a una conversión implícita de CString a HANDLE, que es un tipo typedef de puntero ...

CString x;
delete x;

Lo que obviamente durante el tiempo de ejecución hace cosas muy indefinidas ...

Google para conversiones implícitas en C ++ y STL para obtener algunos de los argumentos en su contra ...


Un ejemplo simple es

2 == '2'  -> true, values are SAME because of type conversion.

2 === '2'  -> false, values are NOT SAME because of no type conversion.

nulo e indefinido son la nada, es decir,

var a;
var b = null;

Aquí ay bno tienen valores. Considerando que, 0, falso y '' son todos los valores. Una cosa común entre todo esto es que todos son valores falsos, lo que significa que todos satisfacen condiciones falsas.

Entonces, el 0, falso y '' juntos forman un subgrupo. Y por otro lado, nulo e indefinido forman el segundo subgrupo. Compruebe las comparaciones en la imagen de abajo. nulo e indefinido sería igual. Los otros tres serían iguales entre sí. Pero, todos ellos son tratados como condiciones falsas en JavaScript.

Esto es lo mismo que cualquier objeto (como {}, matrices, etc.), cadena no vacía y verdadero booleano son todas condiciones verdaderas Pero, no todos son iguales.


Como regla general, generalmente usaría en ===lugar de ==(y en !==lugar de !=).

Las razones se explican en las respuestas anteriores y también Douglas Crockford lo tiene bastante claro ( JavaScript: The Good Parts ).

Sin embargo, hay una única excepción : == nulles una forma eficiente de verificar que 'es nulo o no definido':

if( value == null ){
    // value is either null or undefined
}

Por ejemplo, jQuery 1.9.1 usa este patrón 43 veces, y el verificador de sintaxis JSHint incluso proporciona la eqnullopción relajante por esta razón.

De la guía de estilo jQuery :

Se deben utilizar controles de igualdad estrictos (===) a favor de ==. La única excepción es cuando se comprueba si está indefinido y nulo como nulo.

// Check for both undefined and null values, for some important reason. 
undefOrNull == null;





identity-operator