Selección 2

En este capítulo continúa el estudio de las estructuras selectivas y los elementos que forman parte de las mismas.

Expresiones condicionales

Las expresiones condicionales son aquellas que involucran operadores aritméticos, relacionales y/o lógicos y que devuelven un valor booleano o un valor que puede ser interpretado como booleano.

Algunos problemas condicionales simples pueden ser resueltos empleando dírectamente expresiones condicionales. Por ejemplo (y como ya se vio previamente) para dertermnar si un número es par (o impar) es suficiente verificar si es divisible (o no es divisible) entre 2, es decir si el residuo de su división entre 2 es cero (o no es cero).

En caso simples como el presente, el problema puede ser resuelto en una sola línea empleando una función flecha:

esPar = n => n%2 === 0;

Llamando a la función (probando la función) con los números 124, 311 y 0, se obtiene:

esPar(124)
esPar(311)
esPar(0)

Que, como se puede ver, devuelve los resultados correctos en todos los casos (true si es par y false si no lo es), por lo que se puede concluir que el problema ha sido resuelto correctamente.

Igualmente, se puede resolver el problema de determinar si un número es entero o no con una simple expresión condicional: Si el número tiene parte fraccionaria (si no es divisible entre 1) no es entero, caso contario sí lo es:

esEntero = function(n) {
return n%1 === 0;
};

LLamando a la función (probando la función) con: 124, 911, 124.34, -457 y -93.672, se obtiene:

esEntero(124)
esEntero(911)
esEntero(124.24)
esEntero(-457)
esEntero(-93.672)

Que son los resultados correctos en todos los casos, por lo que se concluye que el problema ha sido resuelto correctamente.

Un número (n) es natural si es entero y positivo. Se incluye en este conjunto al número 0, porque la mayoría de las definiciones matemáticas así lo hacen.

Al igual que en los otros casos, el problema es directamente el resultado de una expresión lógica, donde se determina si el número es divisible entre 1 (si es entero) y si es positivo (mayor o igual a cero):

function esNatural(n) {
return n%1 === 0 && n >= 0;
};

Haciendo correr el programa con 27, 0, -45, 23.45 y -92.14, se obtiene:

esNatural(27)
esNatural(0)
esNatural(-45)
esNatural(23.45)
esNatural(-92.14)

Que son resultados correctos en todos los casos.

La estructura if - else

if - else es la estructura selectiva por excelencia, su lógica, en forma de diagrama de flujo, es:

gojsGraph({divi, modelo:{ "class": "go.GraphLinksModel", "linkFromPortIdProperty": "fromPort", "linkToPortIdProperty": "toPort", "nodeDataArray": [ {"category":"Connector", "text":"...", "key":-8, "loc":"-184 -400"},{"category":"Conditional", "text":"condición", "key":-4, "loc":"-184 -341"},{"category":"Process", "text":"instrucciones A", "key":-2, "loc":"-71 -280"},{"category":"Process", "text":"instrucciones B", "key":-5, "loc":"-287 -280"},{"category":"Connector", "text":"...", "key":-6, "loc":"-178 -224"} ], "linkDataArray": [ {"from":-8, "to":-4, "fromPort":"B", "toPort":"T", "points":[-184,-385.3042461927547,-184,-375.3042461927547,-184,-373.16880171576213,-184,-373.16880171576213,-184,-371.03335723876955,-184,-361.03335723876955]},{"from":-4, "to":-2, "fromPort":"R", "toPort":"T", "visible":true, "points":[-119.50294494628906,-341,-109.50294494628906,-341,-71,-341,-71,-324.13333930969236,-71,-307.2666786193848,-71,-297.2666786193848], "text":"Si"},{"from":-4, "to":-5, "fromPort":"L", "toPort":"T", "visible":true, "points":[-248.49705505371094,-341,-258.49705505371094,-341,-287,-341,-287,-324.13333930969236,-287,-307.2666786193848,-287,-297.2666786193848], "text":"No"},{"from":-5, "to":-6, "fromPort":"B", "toPort":"L", "points":[-287,-262.7333213806152,-287,-252.73332138061522,-287,-224,-244.84787690362265,-224,-202.6957538072453,-224,-192.6957538072453,-224]},{"from":-2, "to":-6, "fromPort":"B", "toPort":"R", "points":[-71,-262.7333213806152,-71,-252.73332138061522,-71,-224,-112.15212309637735,-224,-153.3042461927547,-224,-163.3042461927547,-224]} ]}})

Es decir que si la condición es verdadera, se ejecutan las instrucciones A, caso contrario (else) se ejecutan las instrucciones B. Luego el programa continua con las instrucciones restantes.

En JavaScript, la sintaxis de esta estructura, es:

if (condición) { instrucciones A } else { instrucciones B }

Si en lugar de dos o más instrucciones sólo existe una, las llaves no son necesarias, sin embargo, el escribirlas no es un error y normalmente se escriben por claridad:

if (condición) instrucción_1; else instrucción_2;

El caso contrario (las instrucciones B) es opcional y la estructura puede tener únicamente el caso verdadero (las instrucciones A):

gojsGraph({divi, modelo:{ "class": "go.GraphLinksModel", "linkFromPortIdProperty": "fromPort", "linkToPortIdProperty": "toPort", "nodeDataArray": [ {"category":"Connector", "text":"...", "key":-8, "loc":"-184 -400"},{"category":"Conditional", "text":"condición", "key":-4, "loc":"-184 -341"},{"category":"Process", "text":"instrucciones A", "key":-2, "loc":"-71 -280"},{"category":"Connector", "text":"...", "key":-6, "loc":"-184 -224"} ], "linkDataArray": [ {"from":-8, "to":-4, "fromPort":"B", "toPort":"T", "points":[-184,-385.3042461927547,-184,-375.3042461927547,-184,-373.16880171576213,-184,-373.16880171576213,-184,-371.03335723876955,-184,-361.03335723876955]},{"from":-4, "to":-2, "fromPort":"R", "toPort":"T", "visible":true, "points":[-119.50294494628906,-341,-109.50294494628906,-341,-71,-341,-71,-324.13333930969236,-71,-307.2666786193848,-71,-297.2666786193848], "text":"Si"},{"from":-2, "to":-6, "fromPort":"B", "toPort":"R", "points":[-71,-262.7333213806152,-71,-252.73332138061522,-71,-224,-115.15212309637735,-224,-159.3042461927547,-224,-169.3042461927547,-224]},{"from":-4, "to":-6, "fromPort":"B", "toPort":"T", "visible":true, "points":[-184,-320.9666427612305,-184,-310.9666427612305,-184,-279.83119828423787,-184,-279.83119828423787,-184,-248.6957538072453,-184,-238.6957538072453], "text":"No"} ]}})

En cuyo caso, la sintaxis, es:

if (condición) { instrucciones A }

O si sólo existe una instrucción:

if (condición) instrucción_1;

Como se dijo, en JavaScript, si una instrucción termina con un salto de línea, el punto y coma al final de la misma no es imprescindible, sin embargo, para adquirir buenas costumbres y reducir errores, en la asignatura se debe escribir siempre un punto y coma al final de cada instrucción.

Se debe recordar que, en la calculadora, cuando la instrucción está en la última línea, sólo se debe escribir punto y coma cuando no se quiere mostrar el resultado.

El operador ternario ? - :

El operador ? - : es equivalente a la estructura if - else, tiene la misma lógica que dicha estructura, pero, al ser un operador, se emplea en sentencias de asignación y al interior de expresiones, su sintaxis es:

condición ? instrucción caso verdadero : instrucción caso falso;

A diferencia de la estructura if - else, el caso contrario (:) es obligatorio (no opcional), porque al ser un operador, se requiere el resultado para completar las operaciones de las cuales depende.

Los casos de este operador pueden tener más de una instrucción, pero esas instrucciones deben estar encerradas entre paréntesis y separadas con comas (no entre llaves y separadas con puntos y comas):

condición ? (instr. 1, ..., instr. n) : (instr. 1, ..., instr. n);

Si bien el operador ? - :, puede ser empleado en los mismos casos que la estructura if - else, se emplea sobre todo en los casos donde la lógica es sencilla, porque mientras más compleja es la lógica, más difícil de comprender es el código resultante.

Ejemplos

Par, impar, cero

Para determina si un número entero es par, impar o cero (devolviendo el texto "par", "impar" o "cero"), primero se debe preguntar si el número es cero (porque el cero también es par) luego, descartado el cero, se puede preguntar si el número es par (o impar), siendo el caso por defecto impar (o par).

También se puede preguntar primero si el número es impar, pero luego se debe preguntar si el número es cero (no si es par), siendo el caso por defecto par. Siendo más clara, más flexible y más segura la primera alternativa.

Como se recordará, un número es par si es divisible entre 2 (si el residuo de su división entre 2 es cero) y es impar si el residuo de su división entre 2 es 1.

Por otra parte, como sólo pueden ser pares o impares los números enteros, primero se debe verificar que el número sea entero (que sea divisible entre 1) y de no serlo, se debe suspender la ejecución del programa. Para suspender la ejecución del programa, lanzando un error (por ahora un mensaje), se emplea el comando throw.

Al proceso de verificar que los datos sean del tipo correcto y que estén dentro de los límites permitidos, se denomina validación.

Si no se valida que el número sea entero, la función devolvería un resultado erróneo para los números reales, porque como no son pares, impares o cero, siempre terminaría en el caso por defecto.

Con las anteriores consideraciones, el problema resuelto con la estructura if - else, en una función flecha, es:

parImparCero = n => { if (n%1!==0) throw "El número debe ser entero"; if (n === 0) return "cero"; else if (n%2 === 0) return "par"; else return "impar"; };

En realidad throw lanza el error, suspende la ejecución del código y pasa el control del programa al primer bloque try-catch que lo contenga. Posteriormente se estudiará la estructura try-catch, pero, por el momento es suficiente saber que el error es atrapado por la calculadora y el mensaje mostrado en la celda de resultados.

parImparCero(0)
parImparCero(115)
parImparCero(244)
parImparCero(-115)
parImparCero(-110)
parImparCero(34.53)
El número debe ser entero
parImparCero(-7.3265e2)
El número debe ser entero

Que devuelve los resultados correctos en todos los casos, por lo que se concluye que el problema ha sido resuelto correctamente.

El mismo problema, resuelto con el operador ternario ? - :, como una función estándar, es:

function parImparCero2(n) {
if (n%1!==0) throw "El número debe ser entero.";
return n===0 ? "cero" : n%2===0 ? "par" : "impar"
};

Con la cual se obtienen los mismos resultados que con la versión anterior.

Note que la validación se la hace con if no con ? - :, porque se trata de una pregunta simple (sin else) y como se dijo, en el operador ? - :, el caso contrario (:) es obligatorio.

Año bisiesto

En este ejemplo se resuelve el problema de determinar si un año (un número entero positivo) es (true) o no (false) bisiesto.

Un año es bisiesto si es divisible entre 4 o, si termina en dos ceros, si es divisible entre 400. Así, si el año es 1900, se verifica si 1900 es divisible entre 400 (1900%400==0) o (lo que es lo mismo) si 19 es divisible entre 4 (19%4 == 0).

En este caso, la lógica que resuelve el problema es directa: Se pregunta si el año es divisible entre 100 y de ser así se divide entre 100 y se compara con 0, caso contrario se divide entre 4 y se compara con cero:

Al igual que en el ejemplo previo anterior, se debe validar el número, de manera que se verifique que sea entero y positivo (porque los años son enteros y positivos):

esBisiesto = function(a) { if (a%1!==0 || a<=0) throw "¡El año debe ser entero positivo!"; if (a%100 === 0) return a%400 === 0; else return a%4 === 0; };

La función devuelve siempre un valor booleano: true o false, porque es el resultado de una expresión relacional.

Llamando a la función con diferentes valores de prueba, se obtiene:

esBisiesto(1980)
esBisiesto(1982)
esBisiesto(1996)
esBisiesto(2000)
esBisiesto(2006)
esBisiesto(2012)
esBisiesto(2020)
esBisiesto(-2020)
¡El año debe ser entero positivo!
esBisiesto(2020.32)
¡El año debe ser entero positivo!

El problema resuelto con el operador ternario, siguiendo la misma lógica, es:

esBisiesto2 = function(a) { if (a%1!==0 || a<0) throw "¡El año debe ser entero positivo!"; return a%100===0 ? a%100===0 : a%4===0; };

Con la cual se obtienen los mismos resultados que con la función anterior.

Mayor de 3 números

En este ejemplo se elabora una función que recibe tres números y devuelve el mayor ellos.

Como de costumbre, se pueden plantear varias alternativas de solución. Probablemente la más sencilla consiste en determinar si el primer número es el mayor, de no ser así, se comprueba si el segundo es el mayor y de no ser así el mayor (por defecto) es el tercero.

En este caso, el orden puede ser cambiado sin que en realidad cambie la lógica. La solución preguntando primero si el primer número es el mayor y luego si es el segundo, es:

function mayor(a, b, c) { if (a>=b && a>=c) return a; else if (b>=a && b>=c) return b; else return c; }

Llamando a la función con algunos valores (arrays) de prueba, se obtiene:

mayor(1, 2, 3)
mayor(1, 3, 2)
mayor(3, 2, 1)
mayor(5, 4, 5)
mayor(4, 7, 4)
mayor(8, 8, 8)

Siguiendo la misma lógica, el problema resuelto con el operador ternario, es:

mayor2 = (a, b, c) => { return a>=b && a>=c ? a : b>=a && b>=c ? b : c; };

Función con la que se obtienen los mismos resultados que con la versión anterior.

Ecuación cuadrática

En este ejemplo se elabora una función que calcula y devuelve las dos soluciones de la ecuación cuadrática:

\[ a x^2 + b x + c= 0 \]

Los resultados se calculan con la solución general:

\[ x_{1,2} = \dfrac{-b \pm \sqrt{b^2-4 a c}}{2 a} \]

Desde el punto de vista lógico, el problema es esencialmente el mismo que el resuelto en el primer ejemplo (parImparCero). En este caso, las soluciones dependen de los tres valores que puede tener tomar la expresión dentro de la raíz, denominado discriminante ("d = b2−4ac"). Si el discriminante es positivo, las dos soluciones son reales y distintas, si es cero, las soluciones son iguales (porque la raíz es 0) y si es negativo, las soluciones son complejas (porque la raíz es imaginaria).

El problema resuelto, como una función flecha, es:

cuadratica = (a, b, c) => { const d = b**2-4*a*c; const r = -b/(2*a); const i = Math.sqrt(Math.abs(d))/(2*a); let r1, r2; if (d<0) { r1 = `${r}+${i}i`; r2 = `${r}-${i}i`; } else if (d===0) { r1 = r; r2 = r; } else { r1 = r+i; r2 = r-i; } return [r1, r2]; };

Por claridad y eficiencia, se calculan primero los valores de "r" (la parte de la solución sin la raíz) e "i" (la parte de la solución con la raíz). Se trabaja con el valor absoluto de "d" para poder calcular el valor de la raíz inclusive cuando "d" es negativo. Luego se emplea esos valores para devolver las dos soluciones en los 3 casos.

Dado que una función sólo devuelve un resultado y en este caso existen dos (las dos soluciones) se devuelve un array con esos resultados. En el caso de los números complejos, se devuelven dos cadenas en la forma de números complejos.

Llamando a la función con los coeficientes de algunas ecuaciones cuadráticas, se obtiene:

cuadratica(1, -10, 21)
cuadratica(1, -14, 49)
cuadratica(1, 2, 3)

El problema resuelto como una función estándar, con el operador ternario, es:

function cuadratica2(a, b, c) { const d = b**2-4*a*c; const r = -b/(2*a); const i = Math.sqrt(Math.abs(d))/(2*a); return ( d<0 ? [`${r}+${i}i`, `${r}-${i}i`] : d===0 ? [r, r] : [r+i, r-i] ); }

Con la cual se obtienen los mismos resultados que con la versión anterior.

La estructura "switch"

Si la lógica que resuelve el problema corresponde al siguiente algoritmo:

gojsGraph({divi, modelo: {"class":"go.GraphLinksModel","linkFromPortIdProperty":"fromPort","linkToPortIdProperty":"toPort","nodeDataArray":[{"category":"Conditional","text":"== val1","key":-5,"loc":"-10.000000000000057 -390.9999999999999"},{"category":"Connector","text":"","key":-8,"loc":"-10 -451"},{"category":"Connector","text":"","key":-11,"loc":"-10.645404949583746 9.872429697502579"},{"category":"Conditional","text":"== val2","key":-4,"loc":"-11.000000000000071 -309.99999999999983"},{"category":"Conditional","text":"== val3","key":-6,"loc":"-10.468107424375717 -230.35459505041618"},{"category":"Conditional","text":"== valn","key":-7,"loc":"-10.64540494958382 -135.99999999999997"},{"category":"Process","text":"instrucciones 1","key":-2,"loc":"207 -391"},{"category":"Process","text":"instrucciones 2","key":-9,"loc":"206.99999999999994 -310.21647383353184"},{"category":"Process","text":"instrucciones 3","key":-10,"loc":"207.0000000000001 -230.3154187420928"},{"category":"Process","text":"instrucciones n","key":-12,"loc":"207.00000000000009 -135.99999999999994"},{"category":"Process","text":"instrucciones por defecto","key":-13,"loc":"-10.645404949583778 -52.95027277728926"}],"linkDataArray":[{"from":-5,"to":-2,"fromPort":"R","toPort":"L","visible":true,"points":[63.205093383789006,-390.9999999999999,73.205093383789,-390.9999999999999,106.62326431274411,-390.9999999999999,106.62326431274411,-391,140.04143524169922,-391,150.04143524169922,-391],"text":"Si"},{"from":-4,"to":-9,"fromPort":"R","toPort":"L","visible":true,"points":[62.205093383789006,-309.9999999999999,72.205093383789,-309.9999999999999,106.12326431274411,-309.9999999999999,106.12326431274411,-310.2164738335315,140.04143524169922,-310.2164738335315,150.04143524169922,-310.2164738335315],"text":"Si"},{"from":-6,"to":-10,"fromPort":"R","toPort":"L","visible":true,"points":[62.73698595941336,-230.35459505041618,72.73698595941336,-230.35459505041618,106.38921060055631,-230.35459505041618,106.38921060055631,-230.31541874209282,140.04143524169928,-230.31541874209282,150.04143524169928,-230.31541874209282],"text":"Si"},{"from":-7,"to":-12,"fromPort":"R","toPort":"L","visible":true,"points":[62.20785127600212,-135.9999999999999,72.20785127600212,-135.9999999999999,106.21260254840145,-135.9999999999999,106.21260254840145,-136,140.21735382080078,-136,150.21735382080078,-136],"text":"Si"},{"from":-5,"to":-4,"fromPort":"B","toPort":"T","visible":true,"points":[-10.000000000000057,-370.9666427612304,-10.000000000000057,-360.9666427612304,-10.000000000000057,-350.4999999999999,-11.000000000000057,-350.4999999999999,-11.000000000000057,-340.03335723876944,-11.000000000000057,-330.03335723876944],"text":"No"},{"from":-4,"to":-6,"fromPort":"B","toPort":"T","visible":true,"points":[-11.000000000000057,-289.9666427612304,-11.000000000000057,-279.9666427612304,-11.000000000000057,-270.177297525208,-10.468107424375702,-270.177297525208,-10.468107424375702,-260.3879522891857,-10.468107424375702,-250.3879522891857],"text":"No"},{"from":-6,"to":-7,"fromPort":"B","toPort":"T","visible":true,"points":[-10.468107424375702,-210.32123781164665,-10.468107424375702,-200.32123781164665,-10.468107424375702,-183.17729752520802,-10.64540494958382,-183.17729752520802,-10.64540494958382,-166.0333572387694,-10.64540494958382,-156.0333572387694],"text":"..."},{"from":-7,"to":-13,"fromPort":"B","toPort":"T","visible":true,"points":[-10.64540494958382,-115.96664276123035,-10.64540494958382,-105.96664276123035,-10.64540494958382,-93.0917970789522,-10.645404949583792,-93.0917970789522,-10.645404949583792,-80.21695139667405,-10.645404949583792,-70.21695139667405],"text":"No"},{"from":-8,"to":-5,"fromPort":"B","toPort":"T","points":[-10.000000000000002,-436.3042461927547,-10.000000000000002,-426.3042461927547,-10.000000000000002,-423.6688017157621,-10.000000000000057,-423.6688017157621,-10.000000000000057,-421.03335723876944,-10.000000000000057,-411.03335723876944]},{"from":-13,"to":-11,"fromPort":"B","toPort":"T","points":[-10.645404949583792,-35.683594157904515,-10.645404949583792,-25.683594157904515,-10.645404949583792,-20.25345913382362,-10.645404949583751,-20.25345913382362,-10.645404949583751,-14.823324109742721,-10.645404949583751,-4.823324109742721]},{"from":-12,"to":-11,"fromPort":"R","toPort":"R","points":[263.7826461791992,-136,273.7826461791992,-136,307,-136,307,9.87242969750258,14.05034885766155,9.87242969750258,4.05034885766155,9.87242969750258]},{"from":-10,"to":-11,"fromPort":"R","toPort":"R","points":[263.95856475830084,-230.31541874209282,273.95856475830084,-230.31541874209282,307,-230.31541874209282,307,9.87242969750258,14.05034885766155,9.87242969750258,4.05034885766155,9.87242969750258]},{"from":-9,"to":-11,"fromPort":"R","toPort":"R","points":[263.9585647583008,-310.2164738335315,273.9585647583008,-310.2164738335315,307,-310.2164738335315,307,9.87242969750258,14.05034885766155,9.87242969750258,4.05034885766155,9.87242969750258]},{"from":-2,"to":-11,"fromPort":"R","toPort":"R","points":[263.9585647583008,-391,273.9585647583008,-391,307,-391,307,9.87242969750258,14.05034885766155,9.87242969750258,4.05034885766155,9.87242969750258]}]}})

La lógica de esta estructura es bastante directa: Si el valor de var es igual a uno de los valores (val1, val2, val3, ..., valn), se ejecutan las instrucciones donde se cumple la igualdad y el control del programa sale de la estructura. En caso de no cumplirse ninguna de las igualdades se ejecutan las intrucciones por defecto (si existen) y el control sale de la estructura.

El código respectivo, en JavaScript, es:

switch (valor) {
case valor_1: instrucciones 1; break;
case valor_2: instrucciones 2; break:
case valor_3: instrucciones 3; break;
....
case valor_n: instrucciones n; break;
default: instrucciones por defecto;
}

El comando break hace que el control del programa salga de la estructura switch. Si se cumple una igualdad, pero no existe el comando break, se ejecutan las instrucciones de ese caso y las instrucciones de los casos siguientes, hasta el caso que tenga break y si ningún caso tiene un break hasta que se ejecuta la última instrucción de la estructura.

Normalmente el que un caso no tenga un break es un error, sin embargo, en ocasiones se omite a propósito, para que en dos o más casos se ejecuten las mismas instrucciones.

Ejemplos

Número a día

El propósito de este ejemplo, es el de elaborar una función que convierta un número comprendido entre 1 y 7, en el día de la semana respectivo, siendo el primer día el "domingo".

La lógica es directa, simplemente se recibe el número y si es 1, el resultado es "domingo", si es 2 "lunes", etc. En el caso por defecto se lanza un error informando que el número debe ser un entero comprendido entre 1 y 7:

numADia = n => { let dia = ""; switch (n) { case 1: dia = "domingo"; break; case 2: dia = "lunes"; break; case 3: dia = "martes"; break; case 4: dia = "miércoles"; break; case 5: dia = "jueves"; break; case 6: dia = "viernes"; break; case 7: dia = "sábado"; break; default: throw "El número debe ser un entero comprendido entre 1 y 7"; } return dia; };

Llamando a la función con algunos valores de prueba, se obtiene:

numADia(3)
"martes"
numADia(6)
"viernes"
numADia(1)
"domingo"
numADia(-3)
El número debe ser entero positivo
numADia(15)
El número debe estar comprendido entre 1 y 7

Que son los resultados esperados, por lo que se concluye que el problema ha sido correctamente resuelto.

Días del mes

El propósito de este ejemplo, es el de elaborar una función que reciba el nombre de un mes y el año y devuelva el número de dias que tiene ese mes.

Una vez más la lógica es directa: se recibe el mes y si el mismo es enero, marzo, mayo, julio, agosto, octubre o diciembre, devuelve 31. Si es abril, junio, septiembre o noviembre devuelve 30. Si es febrero devuelve 29 cuando el año es bisiesto y 28 si no lo es. En el caso por defecto, si el mes no corresponde a un mes válido, se lanza un error, informando que

diasDelMes = function(mes, año=2026) { const esBisiesto = año => año%100===0 ? año%400===0 : año%4===0; mes = mes.toLowerCase(); let días = 0; switch (mes) { case "enero": case "marzo": case "mayo": case "julio": case "agosto": case "octubre": case "diciembre": días = 31; break; case "abril": case "junio": case "septiembre": case "noviembre": días = 30; break; case "febrero": días = esBisiesto(año) ? 29 : 28; break; default: throw "Debe mandar un nombre de mes válido"; } return días; };

Como se puede ver, el año es un parámetro por defecto con un valor igual a 2026. Es conveniente que sea un parámetro por defecto porque sólo se requiere el año cuando el mes es febrero, para los otros meses el año es irrelevante.

Para determinar si el año es o no bisiesto, dentro de la función se crea la función (flecha) interna: esBisiesto, que devuelve true si el año es bisiesto y false en caso contrario.

Para que el programa funcione correctamente sin importar si el mes se escribe en mayúsculas, minúsculas o con mayúscula inicial, se convierte a minúsculas el mes recibido, empleando el método toLowerCase (el método opuesto es toUpperCase.

En este ejemplo, dado que los casos correspondientes a los meses de enero, marzo, mayo, julio, agosto, octubre y diciembre deben devolver 31 se omite (a propósito) el comando break excepto, por supuesto, en el mes de diciembre. Se procede de la misma forma con los meses de abril, junio, septiembre y noviembre. En el mes de febrero se llama a la función interna "esBisiesto" para devolver 29 si el año es bisiesto y 28 en caso contrario.

Llamando a la función con algunos valores de prueba, se obtiene:

diasDelMes("Marzo")
diasDelMes("AGOSTO")
diasDelMes("DiCiEmBre")
diasDelMes("junio")
diasDelMes("NOVIEMBRE")
diasDelMes("Febrero")
diasDelMes("febrerO", 2024)
diasDelMes("Setiembre")