multiple - switch javascript conditional
¿Cómo acortar el bloque de mayúsculas y minúsculas convirtiendo un número en un nombre de mes? (13)
¡Ten cuidado!
Lo que debería activar inmediatamente las alarmas es la primera línea:
var month = '''';
- ¿Por qué esta variable se inicializa en una cadena vacía, en lugar de
null
o
undefined
?
Puede que solo haya sido código de hábito o copiado / pegado, pero a menos que lo sepa con certeza, no es seguro ignorarlo cuando está refactorizando el código.
Si usa una matriz de nombres de mes y cambia su código a
var month = months[mm-1];
está cambiando el comportamiento, porque ahora para números fuera del rango, o valores no numéricos, el
month
estará
undefined
.
Puede saber que esto está bien, pero hay muchas situaciones en las que esto sería malo.
Por ejemplo, supongamos que su
switch
está en una función
monthToName(mm)
, y alguien llama a su función de esta manera:
var monthName = monthToName(mm);
if (monthName === '''') {
alert("Please enter a valid month.");
} else {
submitMonth(monthName);
}
Ahora, si cambia a usar una matriz y devuelve
monthName[mm-1]
, el código de llamada ya no funcionará según lo previsto, y enviará valores
undefined
cuando se supone que debe mostrar una advertencia.
No digo que este sea un
buen
código, pero a menos que sepa exactamente cómo se usa el código, no puede hacer suposiciones.
O tal vez la inicialización original estaba allí porque algún código más adelante asume que el
month
siempre será una cadena, y hace algo así como
month.length
: esto dará como resultado una excepción para meses inválidos y potencialmente matará por completo el script de llamada.
Si conoce el contexto completo, por ejemplo, es todo su propio código, y nadie más lo va a usar, y confía en sí mismo, no olvide que realizó el cambio en algún momento en el futuro; puede ser seguro cambiar el comportamiento así, pero muchos errores provienen de este tipo de suposición de que en la vida real es mucho mejor programar a la defensiva y / o documentar el comportamiento a fondo.
La respuesta de Wasmoo es
correcta
(EDITAR: ahora también se han corregido otras respuestas, incluida la aceptada)
: puede usar
months[mm-1] || ''''
months[mm-1] || ''''
o si prefiere que sea más obvio de un vistazo lo que está sucediendo, algo como:
var months = [''January'', ''February'', ...];
var month;
if (mm >= 1 && m <= 12) {
month = months[mm - 1];
} else {
month = ''''; // empty string when not a valid month
}
¿Hay alguna manera de escribir esto en menos líneas, pero aún fácil de leer?
var month = '''';
switch(mm) {
case ''1'':
month = ''January'';
break;
case ''2'':
month = ''February'';
break;
case ''3'':
month = ''March'';
break;
case ''4'':
month = ''April'';
break;
case ''5'':
month = ''May'';
break;
case ''6'':
month = ''June'';
break;
case ''7'':
month = ''July'';
break;
case ''8'':
month = ''August'';
break;
case ''9'':
month = ''September'';
break;
case ''10'':
month = ''October'';
break;
case ''11'':
month = ''November'';
break;
case ''12'':
month = ''December'';
break;
}
¿Qué pasa con no utilizar la matriz en absoluto :)
var objDate = new Date("10/11/2009"),
locale = "en-us",
month = objDate.toLocaleString(locale, { month: "long" });
console.log(month);
// or if you want the shorter date: (also possible to use "narrow" for "O"
console.log(objDate.toLocaleString(locale, { month: "short" }));
según esta respuesta Obtenga el nombre del mes de Fecha de David Storey
Al igual que @vidriduch, me gustaría subrayar la importancia de i20y ("internacionalización") del código en el contexto actual y sugerir la siguiente solución concisa y sólida junto con la prueba unitaria.
function num2month(month, locale) {
if (month != Math.floor(month) || month < 1 || month > 12)
return undefined;
var objDate = new Date(Math.floor(month) + "/1/1970");
return objDate.toLocaleString(locale, {month: "long"});
}
/* Test/demo */
for (mm = 1; mm <= 12; mm++)
document.writeln(num2month(mm, "en") + " " +
num2month(mm, "ar-lb") + "<br/>");
document.writeln(num2month("x", "en") + "<br/>");
document.writeln(num2month(.1, "en") + "<br/>");
document.writeln(num2month(12.5, "en" + "<br/>"));
Trato de mantenerme lo más cerca posible de la pregunta original, es decir, transformar los números del 1 al 12 en nombres de mes, no solo para un caso especial, sino que vuelvo
undefined
en caso de argumentos no válidos, utilizando algunas de las críticas y contenidos de Otras respuestas.
(El cambio de
undefined
a
''''
es trivial, en caso de que se necesite
una
coincidencia
exacta
).
Aquí hay otra opción que usa solo 1 variable y aún aplica el valor predeterminado
''''
cuando
mm
está fuera del rango.
var month = [''January'', ''February'', ''March'',
''April'', ''May'', ''June'', ''July'',
''August'', ''September'', ''October'',
''November'', ''December''
][mm-1] || '''';
Defina una matriz, luego obtenga por índice.
var months = [''January'', ''February'', ...];
var month = months[mm - 1] || '''';
En su lugar, puede crear una matriz y buscar el nombre del mes:
var months = [''January'',''February'',''March'',''April'',''May'',''June'',''July'',''August'',''September'',''October'',''November'',''December'']
var month = months[mm-1] || '''';
Vea la respuesta de @CupawnTae para ver el racional detrás del código
|| ''''
|| ''''
Para completar, me gustaría complementar las respuestas actuales.
Básicamente, puede omitir la palabra clave
break
y devolver directamente un valor apropiado.
Esta táctica es útil si el valor no se puede almacenar en una tabla de búsqueda precalculada.
function foo(mm) {
switch(mm) {
case ''1'': return ''January'';
case ''2'': return ''February'';
case ''3'': return ''March'';
case ''4'': return ''April'';
// [...]
case ''12'': return ''December'';
}
return '''';
}
Una vez más, usar una tabla de búsqueda o funciones de fecha es más sucinto y subjetivamente mejor .
Podrías hacerlo usando una matriz:
var months = [''January'', ''February'', ''March'', ''April'',
''May'', ''June'', ''July'', ''August'',
''September'', ''October'', ''November'', ''December''];
var month = months[mm - 1] || '''';
Prueba esto:
var months = {''1'': ''January'', ''2'': ''February''}; //etc
var month = months[mm];
Tenga en cuenta que
mm
puede ser un entero o una cadena y seguirá funcionando.
Si desea que las claves no existentes den como resultado una cadena vacía
''''
(en lugar de
undefined
), agregue esta línea:
month = (month == undefined) ? '''' : month;
JSFiddle .
Puede escribirlo como una expresión en lugar de un interruptor, utilizando operadores condicionales:
var month =
mm == 1 ? ''January'' :
mm == 2 ? ''February'' :
mm == 3 ? ''March'' :
mm == 4 ? ''April'' :
mm == 5 ? ''May'' :
mm == 6 ? ''June'' :
mm == 7 ? ''July'' :
mm == 8 ? ''August'' :
mm == 9 ? ''September'' :
mm == 10 ? ''October'' :
mm == 11 ? ''November'' :
mm == 12 ? ''December'' :
'''';
Si no ha visto operadores condicionales encadenados antes, esto puede parecer más difícil de leer al principio.
Escribirlo como una expresión hace que un aspecto sea aún más fácil de ver que el código original;
Está claro que la intención del código es asignar un valor a la variable
month
.
Sobre la base de la respuesta anterior de Cupawn Tae, lo acortaría a:
var months = [''January'', ''February'', ...];
var month = (mm >= 1 && mm <= 12) ? months[mm - 1] : '''';
Alternativamente, sí, lo aprecio, menos legible:
var month = months[mm - 1] || ''''; // as mentioned further up
Yo la solución de , pero la ajusto así:
var month = [
''January'',
''February'',
''March'',
''April'',
''May'',
''June'',
''July'',
''August'',
''September'',
''October'',
''November'',
''December''
][mm-1] || '''';
Es exactamente el mismo código, realmente, pero con sangría diferente, que IMO lo hace más legible.
var getMonth=function(month){
//Return string to number.
var strMonth = [''January'', ''February'', ''March'',
''April'', ''May'', ''June'', ''July'',
''August'', ''September'', ''October'',
''November'', ''December''
];
//return number to string.
var intMonth={''January'':1, ''February'':2, ''March'':3,
''April'':4, ''May'':5, ''June'':6, ''July'':7,
''August'':8, ''September'':9, ''October'':10,
''November'':11, ''December'':12
};
//Check type and return
return (typeof month === "number")?strMonth[month-1]:intMonth[month]
}