Tengo una declaración condicional muy larga como la siguiente:
if(test.type == 'itema' || test.type == 'itemb' || test.type == 'itemc' || test.type == 'itemd'){
// do something.
}
Me preguntaba si podría refactorizar esta expresión / declaración en una forma más concisa.
¿Alguna idea sobre cómo lograr esto?
javascript
if-statement
Gato volador
fuente
fuente
in
?||
. (2)switch
declaraciones. (3) expresión regular. (4)~
. jsperf.com/if-statements-test-techsinRespuestas:
Coloque sus valores en una matriz y verifique si su artículo está en la matriz:
Si un navegador que admite no tiene el
Array#includes
método, puede usar este polyfill .Breve explicación del
~
acceso directo tilde:En lugar de verificar si el resultado
indexOf
es>= 0
, hay un pequeño atajo:Aquí está el violín: http://jsfiddle.net/HYJvK/
¿Como funciona esto? Si se encuentra un elemento en la matriz,
indexOf
devuelve su índice. Si no se encontró el artículo, volverá-1
. Sin entrar en demasiados detalles,~
es un operador NOT bit a bit , que regresará0
solo por-1
.Me gusta usar el
~
acceso directo, ya que es más sucinto que hacer una comparación del valor de retorno. Desearía que JavaScript tuviera unain_array
función que devuelva un booleano directamente (similar a PHP), pero eso es solo una ilusión ( Actualización: ahora lo hace. Se llamaincludes
. Ver arriba). Tenga en cuenta que jQueryinArray
, aunque comparte la firma del método PHP, en realidad imita laindexOf
funcionalidad nativa (que es útil en diferentes casos, si el índice es lo que realmente busca).Nota importante: el uso del acceso directo tilde parece estar envuelto en controversia, ya que algunos creen con vehemencia que el código no es lo suficientemente claro y debe evitarse a toda costa (vea los comentarios sobre esta respuesta). Si comparte su sentimiento, debe apegarse a la
.indexOf(...) >= 0
solución.Una pequeña explicación más larga:
Los enteros en JavaScript están firmados, lo que significa que el bit más a la izquierda está reservado como el bit de signo; una bandera para indicar si el número es positivo o negativo, con un
1
ser negativo.Aquí hay algunos números positivos de muestra en formato binario de 32 bits:
Ahora aquí están esos mismos números, pero negativos:
¿Por qué combinaciones tan extrañas para los números negativos? Sencillo. Un número negativo es simplemente el inverso del número positivo + 1; agregar el número negativo al número positivo siempre debería rendir
0
.Para entender esto, hagamos algo de aritmética binaria simple.
Aquí es cómo agregaríamos
-1
a+1
:Y así es como agregaríamos
-15
a+15
:¿Cómo obtenemos esos resultados? Al sumar regularmente, la forma en que nos enseñaron en la escuela: comienzas en la columna de la derecha y sumas todas las filas. Si la suma es mayor que el mayor número de un solo dígito (que en decimal es
9
, pero en binario es1
), llevamos el resto a la siguiente columna.Ahora, como notará, al agregar un número negativo a su número positivo, la columna más a la derecha que no es todo
0
s siempre tendrá dos1
s, que al sumarse resultarán2
. La representación binaria de dos seres10
, que lleva la1
a la siguiente columna, y puso una0
para el resultado de la primera columna. Todas las demás columnas a la izquierda tienen solo una fila con a1
, por lo que el contenido1
de la columna anterior volverá a sumarse2
, lo que luego se transferirá ... Este proceso se repite hasta llegar a la columna más a la izquierda, donde el1
ser transportado no tiene a dónde ir, por lo que se desborda y se pierde, y nos queda con0
s por todas partes.Este sistema se llama Complemento de 2 . Puedes leer más sobre esto aquí:
Representación del complemento 2 para enteros firmados .
Ahora que el curso intensivo en el complemento de 2 ha terminado, notará que
-1
es el único número cuya representación binaria está1
en todas partes.Utilizando el
~
bit a bit NO operador, todos los bits de un número dado se invierten. La única forma de0
volver de invertir todos los bits es si comenzamos con1
todo.Entonces, todo esto fue una forma larga de decir que
~n
solo volverá0
sin
es así-1
.fuente
!== -1
de alguna manera concebible? ¿No es la lógica booleana explícita más apropiada que usar implícitamente la falsedad de cero?!= -1
.Puede usar la instrucción switch con fall thru:
fuente
||
) en Chrome. Ver jsperf.com/if-statements-test-techsinUsando Science: debe hacer lo que idfah dijo y esto para la velocidad más rápida mientras mantiene el código corto:
ESTO ES MÁS RÁPIDO QUE EL
~
MÉTODOhttp://jsperf.com/if-statements-test-techsin (Conjunto superior: Chrome, conjunto inferior: Firefox)
Conclusión
Si posibilidades son pocas y sabe que ciertas personas tienen más probabilidades de ocurrir que se obtiene el máximo rendimiento
if ||
,switch fall through
yif(obj[keyval])
.Si las posibilidades son muchas , y cualquiera de ellas podría ser la más frecuente, en otras palabras, no puede saber cuál es más probable que ocurra que obtener el mayor rendimiento de la búsqueda de objetos
if(obj[keyval])
yregex
si eso encaja.http://jsperf.com/if-statements-test-techsin/12
actualizaré si surge algo nuevo.
fuente
switch case
es el método más rápido?if ( ...||...||...)...
obj["itemX"]
es extremadamente rápido si n es grande. Básicamente, lo rápido depende del contexto. Que te diviertas.Si está comparando con cadenas y hay un patrón, considere usar expresiones regulares.
De lo contrario, sospecho que intentar acortarlo solo ofuscará su código. Considere simplemente envolver las líneas para que quede bonito.
fuente
(test.type == 'itemf' && foo.mode == 'detailed')
)Usar un objeto como una matriz asociativa es algo bastante común, pero dado que JavaScript no tiene un conjunto nativo, también puede usar objetos como conjuntos baratos.
fuente
if
El condicional de la declaración de @dcarson OP toma 78 caracteres si elimina todos los espacios en blanco. El mío tiene 54 si se escribe así:test.type in {"itema":1,"itemb":1,"itemc":1,"itemd":1}
. Básicamente, usa cuatro caracteres por cada dos minas para cada tecla adicional.o si los artículos no son tan uniformes, entonces:
fuente
Excelentes respuestas, pero podría hacer que el código sea mucho más legible envolviendo uno de ellos en una función.
Esto es complejo si la declaración, cuando usted (u otra persona) lea el código dentro de unos años, estará escaneando para encontrar la sección para comprender lo que está sucediendo. Una declaración con este nivel de lógica empresarial le hará tropezar durante unos segundos mientras trabaja en lo que está probando. Donde un código como este, le permitirá continuar escaneando.
Asigne un nombre explícito a su función para que sea inmediatamente obvio lo que está probando y su código será mucho más fácil de escanear y comprender.
fuente
// CheckIfBusinessRuleIsTrue
?Puede poner todas las respuestas en un conjunto de Javascript y luego simplemente llamar
.contains()
al conjunto.Aún debe declarar todos los contenidos, pero la llamada en línea será más corta.
Algo como:
fuente
Una de mis formas favoritas de lograr esto es con una biblioteca como underscore.js ...
http://underscorejs.org/#some
fuente
contains
es posiblemente una mejor solución quesome
some
es una función en el prototipo de matriz en EC5.otra forma u otra forma increíble que encontré es esto ...
Por supuesto, como puede ver, esto lleva las cosas un paso más allá y facilita la lógica de seguimiento.
http://snook.ca/archives/javascript/testing_for_a_v
utilizando operadores como ~ && || ((), ()) ~~ está bien solo si su código se rompe más adelante. No sabrás por dónde empezar. Entonces la legibilidad es GRANDE.
si es necesario, puedes hacerlo más corto.
y si quieres hacer inversa
fuente
Simplemente use una
switch
declaración en lugar de unaif
declaración:Switch
también funciona más rápido que comparar muchos condicionales dentro de unif
fuente
Para listas muy largas de cadenas, esta idea ahorraría algunos caracteres (sin decir que lo recomendaría en la vida real, pero debería funcionar).
Elija un carácter que sepa que no aparecerá en su tipo de prueba, úselo como delimitador, péguelos en una cadena larga y busque eso:
Si sus cadenas están más restringidas, incluso podría omitir los delimitadores ...
... pero tendría que tener cuidado con los falsos positivos en ese caso (por ejemplo, "embite" coincidiría en esa versión)
fuente
Para facilitar la lectura, cree una función para la prueba (sí, una función de una línea):
entonces llámalo:
fuente
Creo que hay 2 objetivos al escribir este tipo de condición if.
Como tal, a veces el n. ° 1 puede ser el más rápido, pero tomaré el n. ° 2 para facilitar el mantenimiento más adelante. Dependiendo del escenario, a menudo optaré por una variación de la respuesta de Walter.
Para comenzar, tengo una función disponible globalmente como parte de mi biblioteca existente.
y luego, cuando realmente quiero ejecutar una condición if similar a la suya, crearía un objeto con una lista de los valores válidos:
No es tan rápido como una declaración de cambio / caso y un poco más detallado que algunos de los otros ejemplos, pero a menudo obtengo la reutilización del objeto en otra parte del código que puede ser bastante útil.
Piggybacking en una de las muestras jsperf hechas anteriormente. Agregué esta prueba y una variación para comparar velocidades. http://jsperf.com/if-statements-test-techsin/6 Lo más interesante que noté es que ciertos combos de prueba en Firefox son mucho más rápidos que incluso Chrome.
fuente
Esto se puede resolver con un simple bucle for:
Usamos la primera sección del ciclo for para inicializar los argumentos que desea hacer coincidir, la segunda sección para detener la ejecución del ciclo for y la tercera sección para hacer que el ciclo finalmente salga.
fuente