arrow&v

3. Elementos básicos


Variables


Las variables son contenedores que almacenan valores. En JavaScript se deben declarar antes de usarlo y eso se puede hacer con las palabras clave let o var. Por ejemplo:



Las variables se pueden declarar sin asignarles un valor inicial. La diferencia entre var y let es sutil pero valiosa cuando se consideran los ámbitos (scopes). Si la intención de uso de la variable se limita a lo interno de un bloque de código, se utiliza la palabra clave let. Mientras que al utilizar la palabra var dependerá del ámbito en que se declara la validez en una parte del código u otra.


Con esto ambas variables misMonedas y elJardinero, están listas para asignarles valores o ser leídas en el código de este punto en adelante y hasta a donde se defina su ámbito. Se le asignan valores a las variables ya declaradas así:




Y se pueden hacer los cambios que se requieran al valor de la variable en nuestro código cuando sea pertinente. Este ejemplo muestra como le asignaríamos 0 a la variable misMonedas:





Nótese que solo se han asignado valores numéricos a la variable misMonedas. Pero se pueden asignar valores de diferentes tipos a una variable como veremos en la próxima sección. Por ahora, observe la asignación de un valor tipo «string» a la otra variable que se declaró:



En JavaScript, a diferencia de algunos otros lenguajes más antiguos, las variables no tienen un tipo definido, pero los valores que se les puede asignar a variables sí. A esta característica se le dice “tipado dinámico” lo cual es diferente a lenguajes de “tipado fuerte” como C, C++ y Java. En el tipado fuerte, la variable tiene un “tipo”. Es decir, una naturaleza específica de valor a contener. Si una variable es tipo “string” únicamente puede recibir valores tipo “string”.


Tipos de datos principales en JavaScript


Boolean (booleano):


Los valores de este tipo representan una entidad lógica y solo pueden tener dos valores: true O false.Es muy útil para escribir código que es fácil de entender pues es posible usarlos en declaraciones de control de flujo para simplificar el entendimiento de la toma de decisiones.


Por ejemplo, si se quiere evaluar una expresión muchas veces en el código, se puede asignar el resultado de la evaluación, que retorna un valor booleano; a una variable y así escribir mucho menos código. En el siguiente ejemplo, se observa como la calificación de un cliente puede ser aceptable o no. El valor lógico true corresponde a un cliente aceptable y el false a uno no aceptable. Para que el cliente sea aceptable, el valor edad debe ser mayor o igual a 25, el valor de la capacidad de crédito mayor a 580 y la ciudad debe ser diferente de Los Angeles. En lugar de evaluar todas esas características en distintos lugares del programa, se puede almacenar el resultado de la evaluación en la variable es_cliente_aceptable.



No se está comparando la variable es_cliente_aceptable explícitamente contra true o false porque no es necesario en controles de flujo, pero podría hacerse así y se interpretaría de la misma forma.


Nótese que los valores booleanos se pueden invertir de true a false o al revés con solo usar el símbolo clave de negación antes de la variable o expresión, que en JavaScript seria ”!”


Nulo ( null )


El tipo “Null” se usa para representar un valor “nulo” por lo cual solo tiene un valor posible: null. Esto es útil cuando se requiere “anular” una variable para asegurar que no se use de forma incorrecta en otra parte del código a donde no sea válido el último valor que se le había asignado.


También se puede usar para cuando una función no logra resolver un valor a regresar, pero se necesita consistencia en la forma de responder la función. En estos casos simplemente se retorna el valor “null” para que el código que llama la función pueda fácilmente revisar si se retornó algo válido o no.


Indefinido (undefined)


Todas las variables que no se les ha asignado un valor se les asigna el tipo “undefined”. A diferencia de otros lenguajes de programación “compilados” donde se revisan variables no definidas antes de generar un “ejecutable”, en JavaScript es posible ejecutar un programa que se refiera a variables que aún no se les ha asignado ningún valor, pero al hacerlo se recibe un error. En general no es buena práctica diseñar un programar que “tolere” variables no declaradas, entonces la utilidad de este tipo de dato es para justamente entender lo que está pasando al recibir un error si se intenta accederlos.


Números (number)


Existen dos tipos de números: Number y BigInt


El tipo Number es un valor binario de 64 bits en formato IEE 754 de doble precisión (números entre -(2^53 − 1) y 2^53 − 1). Además de representar números de punto flotante, el tipo número tiene tres valores simbólicos: : +Infinity, -Infinity, y NaN ("No un Numero").


BigInt se puede usar para representar números enteros en el formato de precisión arbitraria. Esto significa que el número puede ser tan grande como la memoria disponible para el programa. Con lo cual se puede ir mucho más allá de lo permitido con el tipo “Number” regular (solo 64 bits).


Objeto number


Hay un objeto integrado llamado Number en JavaScript que contiene las propiedades para constantes numéricas como valor máximo (Number.MAX_VALUE), infinidad positiva (Number.POSITIVE_INFINITY) y otros. También contiene funciones de conversiones de otros formatos como seria pasar de una cadena de caracteres (string) a un número: Number.parseInt()


Aquí algunos ejemplos. Primero se asigna una cadena de caracteres a una variable:



Luego se convierte a un número:



Ahora nótese como se puede mostrar el valor máximo que puede tener un número:



Más detalles del objecto Number acá:

https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Number


El objeto Math

El objecto integrado Math permite hacer una gran cantidad de operaciones comunes en matemática ya que comprende funciones trigonométricas, logarítmicas, exponenciales y otras. Por ejemplo, podemos se puede obtener el valor de PI así:




Y aplicarle funciones trigonométricas de forma muy intuitiva. Esta es la sentencia para convertir 90 grados a radianes:



Y ahora calcular el seno de 90 grados (Esto porque la función Math.sin() solo toma parámetros en radianes):



Para generar números pseudoaleatorios (entre el 0 y el 1):



Y para calcular el mínimo en una lista de números:



Mas detalles del objecto Math acá:

https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Math


Cadenas de caracteres (Strings)

Las cadenas de caracteres o “strings” son una secuencia de caracteres que se usa para representar un texto. En JavaScript las cadenas se pueden manipular fácilmente usando operadores como +:



También se pueden convertir números a cadenas de texto usando ese mismo operador:



NOTA: Solo el operador + convierte números a cadenas a como se necesite, los otros más bien buscan convertir cadenas a números para ejecutar operaciones matemáticas. Por ejemplo:



Pero si se necesita convertir de cadenas a números sin estar en el contexto de una operación matemática, hay funciones específicas para cada tipo:



Uso de caracteres especiales en cadenas


Las cadenas pueden tener caracteres especiales para incluir algunos elementos que no se pueden imprimir ni visualizar fácilmente o para especificar caracteres propios de las declaraciones de las cadenas, tales como serían las comillas.


Los caracteres especiales en JavaScript son los siguientes:




A continuación un ejemplo donde se agregan comillas a un texto de esta manera:



Al ejecutar, el resultado de ese código seria:



Operaciones comunes de cadenas de caracteres


Es muy común el tener que obtener algún texto de un servicio o como una respuesta de un usuario y posteriorme tener que buscar algo dentro de ese mismo texto o manipularlo más allá de simplemente combinar cadenas. Hay una gran variedad de funciones en JavaScript que se pueden ejecutar como métodos de literales o variables con valores tipo cadena. Aquí se describen solo una muestra de los más usados:


Acceder a un carácter dentro de una cadena


Con la función charAt() se puede obtener el carácter de una posición específica de la cadena. Por ejemplo, si el código recibe una cadena de caracteres que se sabe con anticipación que contiene la palabra "Capitulo” seguido de un espacio y luego un número de un digito, se puede buscar ese dígito en particular en la posición 9 (se cuenta desde cero). Entonces, si se tiene la cadena "Capitulo 9” y "Capitulo 6", con la funcion charAt(9) siempre se obtendrá el carácter que representa el número del capítulo:



Extraer un pedazo de cadena:


Si se necesita extraer una parte de la cadena y se sabe la posición exacta de los caracteres que se necesitan, se utiliza la función substring() para obtenerlos. Por ejemplo, para extraer el título de la cadena1 abajo asumiendo que se conoce que siempre empieza con el texto "Capitulo” más un espacio, un dígito numérico, dos puntos y otro espacio, entonces el titulo inicia en la posición 12 (empezando desde cero igual que en charAt()):



Si solo se indica un parámetro en la función substring()devolverá una cadena que contiene todos los caracteres de la posición a partir del índice inicial que se indicó. Pero si se le agrega un segundo parámetro, lo va a interpretar como el índice hasta el cual obtener caracteres. De esta forma se puede extraer una porción específica de caracteres dentro de la cadena. Observe el uso de esta función para obtener el pronombre del título de la variable cadena1:



Búsqueda básica en cadenas


En los dos ejemplos anteriores se asume que se sabe exactamente donde están las cosas en la cadena. Pero ¿qué tal si hay variaciones? Entonces se debe buscar algo en particular en la cadena. Entonces, siguiendo el mismo ejemplo de antes, asumiendo que el número de capítulo pueda tener más de 1 dígito, pero siempre el título comienza después de los 2 puntos y un espacio. Entonces primero se obtiene la posición del título usando la función indexOf() y luego se extrae así:



Note que es necesario sumar 2 a la posición del carácter ': ‘ en la cadena. Ya que el titulo realmente empieza en el carácter a la derecha del carácter de espacio.


Busqueda avanzada en cadenas


Otra forma de búsqueda más exacta es usando expresiones regulares (RegExp) para especificar patrones de cualquier nivel de complejidad para encontrar texto en cadenas.


A continuación un ejemplo de cómo extraer referencias a series de televisión basado en temporadas y episodios ("seasons” y “episodes” en inglés) con lo cual el formato suele ser la letra S con un numero de 2 digitos para representar la temporada seguido de la letra E con otro número de 2 dígitos representando el número del episodio.


En expresiones regulares, eso se puede especificar así: /S[0-9][0-9]E[0-9][0-9]/


En el ejemplo de abajo se puede ver también como al agregar las letras ‘gi’ se indica que es una búsqueda global (no solo cuando primero encuentre una incidencia) y que haga caso omiso a si las letras son mayúsculas o minúsculas.


No se va a profundizar en el tema de expresiones regulares, pero sería muy útil que dedique tiempo a una herramienta en línea donde se pueda construir y probar todo tipo de expresiones regulares. Aquí hay un par de ejemplos:


https://regexr.com/

https://regexper.com/


Pero regresando al ejemplo concreto, se puede observar abajo que después de asignar la cadena de caracteres a buscar a la variable cadena y la expresion regular a expresion, solo queda llamar la función match() de la cadena de caracteres y pasar como parámetro la variable expresion:



Si se ejecuta ese programa ya sea luego de copiarlo a un archivo y ejecutándolo, o directamente en el comando de línea de node.js se obtendrá el siguiente resultado:



Más detalles del uso de la función match() para hacer búsquedas usando expresiones regulares lo puedes ver acá:

https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/String/match


Más detalles del uso de cadenas de caracteres en general y ejemplos acá:

https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/String


Constantes


Una constante es un elemento similar a una variable, con las mismas reglas de nombres y ámbitos, pero que no puede ser modificada tras haber sido declarada con la palabra clave const.


Puedes practicar con el siguiente ejemplo:



(Recuerde que luego de asignar PI=3.1415 el mensaje recibido de “undefined” es simplemente porque la línea de comando interactiva de node trata de imprimir lo que retorne cada función y en una asignación no se retorna nada).


Y al intentar asignarle un valor se obtiene el mensaje de error que recuerda que se trata de una constante.


Ámbitos de variables (Scopes)


Este tema es fundamental ya que si no se entienden los ámbitos de variables, es muy probable que se asigne incorrectamente un valor a una variable o bien se evalúe incorrectamente un valor, al referirse a una variable cuyo nombre está correcto, pero se está referenciando en un contexto distinto al que se creía.


Cuando se declara una variable fuera del contexto de una función, se considera ser “global” pues aplica a todo el código siendo escrito en el mismo archivo. Pero si es declarada ya dentro de una función, se considera una variable local.


Por ejemplo:



Al ejecutar este código se obtiene este resultado:



Esto es porque cuando se imprime el valor de X dentro de la función, la declaración en la línea anterior es la que se considera válida; mientras que cuando se imprime fuera de la función, retorna el valor “global” de la primera línea.


En general no es buena idea depender de variables globales pues en programas muy largos puede volverse complicado el entender cuáles procesos pueden estar afectando el valor de esas variables, ya que puede ser código en cualquier parte. Es mejor usar variables locales y aceptar parámetros en funciones y devolver resultados, pero se verán más detalles de esos mecanismos en la sección de funciones.


Elevación de funciones y variables (hoisting)


Una característica peculiar de JavaScript es que podemos referirnos a funciones y variables que son declaradas más adelante en el código sin generar errores en ejecución.


Esto se logra porque JavaScript “eleva” o sube hacia la parte superior del programa todas las declaraciones de variables, incluyendo expresiones de funciones hacia el principio del código y les asigna un valor indefinido (undefined). Entonces sigue siendo una buena práctica el declarar las variables lo más pronto posible para que sea más fácil de leer y no encontrarse con valores indefinidos. Pero cuando se trata de funciones si es una gran conveniencia poder hacerlo en cualquier parte del programa, pues en ocasiones es necesario llamar una función desde una parte anterior a donde se había declarado y no es indispensable reorganizar todo el código para lograrlo.


Así entonces, este código va a correr exactamente igual al que vimos en la sección anterior:



El resultado sigue siendo:



Pero si se mueve la declaración var X=10 hasta la última sentencia, al imprimirlo con console.log(`Afuera es ${x}`) el resultado sera:



Esto debido a que el llamado a la variable x se produce antes de la asignación. No genera error debido a la declaración “automática inicial” de JavaScript. Pero muestra que la variable no está definida ya que la asignación del valor se da posterior a la llamada para impresión.


Fechas


JavaScript no tiene un valor primitivo para fechas, pero si tiene el objecto innato Date que posee muchas funciones enfocadas en obtener, establecer y manipular fechas. Como en muchos otros lenguajes de programación, la definición de datos relacionados a fechas se basa en el número de milisegundos desde el primero de enero de 1970 a las 0:00:00, lo cual se conoce también con UNIX Epoch o Posix Time. No es el único mecanismo de almacenamiento y cálculo de fechas, pero sí es el más popular por ser usado en todas las variantes de los sistemas operativos Unix y Linux.


Hay varias herramientas en línea para ayudar a convertir de Epoch a fechas y viceversa lo cual puede ser útil para entender mejor el concepto. Este es un ejemplo: https://espanol.epochconverter.com/


Explore el uso del objeto Date() de JavaScript creando una nueva instancia del objecto y asignándoselo a una variable. Si no se usan parámetros al especificar new Date(), se retorna un objecto de Date que contiene la fecha/hora en el momento que se invocó la función:



Claro, lo más probable es que esa fecha/hora se necesite para imprimir, mostrar en la pantalla o para hacer algún calculo; con lo que conviene pasarlo a una cadena de caracteres o a un número (número de milisegundos desde Epoch).


Para convertirla a una cadena de caracteres en español con formato de fecha y hora de España se puede usar la función toLocaleTimeString() con las opciones mostradas abajo:



Si se necesita obtener aspectos específicos de fecha y hora para imprimir en algún formato más allá de los que se pueden obtener con las opciones de una función como toLocaleTimeString() se pueden usar funciones como getDay(), getMonth(), getFullYear(), getMinutes(), getHours() y otros. Por ejemplo, se puede construir un texto combinándolos de esta forma usando planillas literales:



También es posible obtener el número de milisegundos desde Unix Epoch para hacer operaciones matemáticas y comparaciones.



Pero también se pueden hacer comparaciones directamente sobre el objecto de Date como se observa abajo, donde se asigna a la variable fecha_expiracion una fecha en el pasado y luego se compara con lo que ya se había obtenido en la variable ahora para ver si la fecha de expiración está en el pasado al ser menor que la fecha de ahora:



Más detalles y ejemplos usando el objecto Date se pueden ver acá: https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Date


Arreglos (Arrays)


Un array es una lista de objetos similares y contiene métodos para efectuar operaciones de recorrido y mutación. Para declarar un array al cual se le piensa asignar una lista de números. Se puede inicializar sin miembros y sin saber siquiera el tipo de datos que va a contener así:



O bien asignarle algunos elementos:



Para acceder a un miembro del array, solo tenemos que especificar su índice, el cual comienza en cero. Entonces el array lista_medidas contiene ahorita 3 elementos que se pueden acceder usando índices 0,1 y 2. Por ejemplo, el valor de la posición 1 es 65:



Ahora, para cambiar los valores de la lista basta con una simple asignación usando el índice correcto. Observe la sustitución del valor 65 por 105:



Para extraer la cantidad de elementos presentes en la lista usamos la propiedad length:



Y para recorrer la lista, se utiliza uno de los ciclos de JavaScript que vamos a ver más adelante. En este ejemplo, el ciclo for para imprimir todos los elementos de la lista alcanza con 2 líneas de código:



Aunque la forma más elegante y abreviada de “recorrer” el array es con el método innato forEach:



Más detalles acerca de operaciones de arrays tales como agregar/eliminar elementos y dividirlos/unirlos se pueden encontrar acá: https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array


Uso de Objetos como diccionarios


En JavaScript, a diferencia de otros lenguajes de programación populares como Python, no hay diccionarios como tal, pero se puedes usar objetos literales con el mismo propósito y funcionan bastante bien como sustituto de lo que en otros lenguajes se refieren a “diccionarios”. Por ejemplo, copia el código en el bloque abajo a un editor de texto y guárdalo como diccionario.js:



Ahora ejecuta o «corre» el código:



El resultado debería decir lo siguiente:



Como pudo observar, es posible obtener el valor de cualquier clave del “diccionario” usando la notación “suscrito” (objecto[‘clave’]) o la notación punto: (objeto.clave)

También se puede asignar valores usando la misma notación, pero asignado con el símbolo ‘=’ al final:



También es posible eliminar una clave con el comando delete:



En el último comando del programa podemos ver como imprimir a la consola el objeto completo. El comando console.log() sabe leer el objeto e imprimirlo de una forma amigable para los seres humanos.