Las constantes son como promesas: una vez hechas, más vale que no cambien. Las variables, en cambio, son como tus planes de sábado noche.
En este capítulo vamos a abordar la creación y uso de constantes y variables en JS, así como cuestiones relacionadas como las pautas para nombrarlas. Puesto que el curso está orientado a personas con nociones de programación, la explicación sobre qué es una variable y en qué se diferencia de una constante quedan fuera de su alcance.
En este capítulo se presentan sencillos ejemplos de código para ilustrar los contenidos. Todos ellos pueden ser ejecutados con node en modo REPL (Read-Eval-Print Loop), tal como describimos en el capítulo Node.JS del bloque introductorio. Por supuesto puedes también ejecutarlos creando un archivo .js y pegando el código en él para luego llamar a node, pero creo que es más rápido y visual usar REPL.
Pautas de nombrado
Como se adelantó ya el el capítulo introductorio de esta unidad didáctica, existen una serie de convenciones a la hora de programar en cualquier lenguaje de programación que se recogen el lo que se da a llamar Guía de Estilos. Como dijimos también, en este curso vamos a seguir la guía de estilos de MDN.
Una de las cuestiones cubiertas por las guías de estilos es el nombre elegido para constantes y variables. En JS, tanto constantes como variables se nombran utilizando notación camelCase: La primera letra en minúsculas, sin guiones para separar palabras, y la primera letra de cada palabra adicional en mayúsculas. Algunos ejemplos pueden ser result, resultValue o oneTwoThree. Para acabar, aunque no suele ser un aspecto cubierto por las guías de estilo, en este curso vamos a utilizar indistintamente el inglés y el español para los nombres de constantes, variables, funciones y archivos.
Variables
El modo de definir una variable en JS es utilizar la palabra reservada let:
// Este código define la variable 'message'
// con valor "Hola, mundo!"
// e imprime su valor por pantalla
let message = "Hola, mundo!"
console.log(message)
Aquellos que vengan de lenguajes de programación fuertemente tipados se habrán dado cuenta que en JS no hace falta definir el tipo de la variable: JS no es un lenguaje de programación fuertemente tipado.
De hecho no solo no lo es, sino que además es dinámicamente tipado: una variable definida con un tipo de valor puede cambiar de tipo sin ningún problema, tal como muestra el ejemplo siguiente:
// Imprime la cadena "Hola, mundo!"
let message = "Hola, mundo!"
console.log(message)
// Imprime el número 123457
message = 123456
console.log(message + 1)
¿Muy loco todo, verdad? Pues no se vayan todavía, que aún hay más. De hecho, no hace falta definir la variable con la palabra reservada let ni hace falta asignar un valor al definir una variable:
// Puesto que 'noVar" no se ha definido,
// esta línea genera un error
// "Uncaught ReferenceError: noVar is not defined"
console.log(noVar)
// Se define 'undefinedVar' sin asignarle valor
// Se imprimirá "undefined" por la salida estándar,
// pero no se generará ningún error
let undefinedVar
console.log(undefinedVar)
// Se define 'message' sin usar let.
// Se imprimirá "Hola, mundo!" por la salida estándar
message = "Hola mundo!"
console.log(message)
// Se declaran variables en bloque
// con y sin let
// Se imprimirá "Hola, mundo!" por la salida estándar
// cuatro veces
let a = b = "Hola, mundo!"
console.log(a)
console.log(b)
c = d = "Hola, mundo!"
console.log(c)
console.log(d)
Creo que en este punto empiezas a hacerte una idea del tremendo desastre que podría llegar a ser un programa escrito en JS si no se le aplicasen las normas definidas en las guías de estilo u otras soluciones que veremos más adelante.
Mi consejo es que, en lo relativo a la definición de variables, sigas estas normas:
- Define las variables usando la palabra reservada
let - Asigna un valor inicial en el momento de la definición a no ser que el valor inicial de la variable sea explícitamente desconocido
- No definas variables en bloque
- No cambies el tipo de los valores almacenados por una variable, mantén el tipado que asignaste en su definición
let y var
Hemos visto que la palabra reservada let nos permite definir variables. JS permite además definir variables utilizando la palabra reservada var.
Ya hemos visto que JS puede llegar a ser un lenguaje de programación bastante anárquico, caldo de cultivo para pésimos programadores. Tanto la guía de estilos de MDN como Douglas Crockford (uno de los creadores de JS) como tantos otros, incluyéndome a mi, abogamos por olvidar la palabra reservada var y, en la medida de lo posible, llevarla al Monte del Destino y dejar que se pudra allí.
Ni siquiera voy a molestarme en explicar las razones de tal odio: olvídate de var y usa solamente let. Serás más feliz y vivirás más años.
Constantes
Por definición una constante es una variable cuyo valor no puede cambiar una vez definido. Las constantes en JS se definen con la palabra reservada const.
// Este código define la constante 'message'
// con valor "Hola, mundo!"
// e imprime su valor por pantalla
const message = "Hola, mundo!"
console.log(message)
JS no otorga el grado de libertinaje a las constantes que otorga a las variables, y ciertas atrocidades de las mostradas en la sección anterior no se permiten: No pueden declararse constantes sin la palabra reservada const o sin establecer explícitamente su valor:
// No se puede definir una constante
// sin asignarle un valor
const message
// No se puede definir una constante
// sin usar la palabra reservada "const"
message = "Esto es una variable, no una constante"
Tampoco pueden definirse varias constantes en una sola instrucción, aunque ciertas instrucciones sugieran lo contrario:
// Parece una definición múltiple
// de constantes, pero no lo es:
// a es la única constante, b es una variable
const a = b = 1
// Esta instrucción genera un error
// "Uncaught TypeError: Assignment to constant variable"
a = 0
// Puesto que b es una variable,
// esta instrucción no genera un error
b = 0
De nuevo puedes ver lo peligroso de JS si no se mantiene bajo el control de una guía de estilos y de ciertas buenas prácticas. En lo relativo a constantes, las buenas prácticas a aplicar son:
- Cuando el valor no vaya a cambiar, define una constante en lugar de una variable
- No definas constantes en bloque: Parece que defines constantes pero en realidad defines constantes y variables
Contexto de constantes y variables
La unidad básica en un lenguaje de programación es la instrucción, siendo un programa la suma de un conjunto de instrucciones.
Ciertas funcionalidades de los lenguajes de programación requieren agrupar las instrucciones en bloques de instrucciones, que se acotan con lo que se conocen como símbolos de inicio y fin de bloque de instrucción. En JS, dichos símbolos son los caracteres { y }.
El siguiente ejemplo muestra el uso de dichos caracteres para crear bloques de instrucción. Ten en cuenta que agrupar instrucciones en bloques como muestra el ejemplo no tiene absolutamente ningún sentido: Los bloques se han definido únicamente por motivos didácticos (más adelante veremos cuándo son necesarios los bloques de instrucciones).
// Esto es una instrucción
console.log("Hola, mundo!")
// Esto es un bloque de instrucciones
{
console.log("Hola otra vez, mundo!")
console.log("Adiós, mundo cruel!")
}
Los bloques de instrucciones se nombran en este capítulo porque un bloque de instrucciones define y limita el ámbito de existencia de una constante o variable, o dicho de otro modo, define el contexto de una constante o una variable: Una constante o variable solamente existe dentro del bloque de código, o contexto, en el que se define.
// La variable 'message' solamente existe
// en el contexto del bloque de código en que se define.
// El siguiente bloque de código imprime "Hola, mundo!"
{
let message = "Hola, mundo!"
console.log(message)
}
// Fuera del contexto donde se definió
// la variable 'message' ya no existe
// y la siguiente instrucción generará un error
// "Uncaught ReferenceError: message is not defined"
console.log(message)
JS no permite redefinir constantes y variables en el mismo contexto, pero sí permite hacerlo en contextos distintos e incluso anidados como muestra el siguiente ejemplo.
// La variable 'message'
// se define en el contexto actual
let message = "Hola, mundo!"
// Redefinir 'message' generaría un error
// "Uncaught SyntaxError: Identifier 'message'
// has already been declared"
{
// Puesto que se definió en un contexto padre,
// la variable message existe en el contexto anidado.
// La siguiente instrucción imprime "Hola, mundo!"
console.log(message)
// La variable 'message' se redefine
// en un contexto anidado
let message = "Adiós, mundo!"
// La siguiente instrucción imprime "Adiós, mundo!"
console.log(message)
}
// En el contexto actual 'message' existe
// con el valor que se asignó en su creación.
// La siguiente instrucción imprime "Hola, mundo!"
console.log(message)
Lo bueno y lo malo de los contextos
En general, redefinir una constante o variable en un contexto anidado es una pésima idea, y sería poquísimos los escenarios (yo diría que ninguno) en que dicha redefinición estaría justificada.
Si nos olvidamos de la redefinición, la esencia del concepto de contexto es que una constante o variable existe solamente en el ámbito del bloque de código donde se definió, lo que nos permite definirlas en distintos contextos, o bloques de código, sin compartir sus valores, como se muestra en el siguiente fragmento de código:
// Un bloque de código
{
// La variable 'message'
// se define en el contexto de un bloque
let message = "Hola, mundo!"
// La siguiente instrucción imprime "Hola, mundo!"
console.log(message)
}
// Otro bloque de código
{
// La variable 'message' se define
// en el contexto de otro bloque.
// NO se está redefiniendo, puesto que
// estamos fuera del contexto de la definición anterior
let message = "Adiós, mundo!"
// La siguiente instrucción imprime "Adiós, mundo!"
console.log(message)
}
Todo esto de los bloques parece tener poco sentido en este capítulo, pero es necesario abordarlo para cubrir todo lo relativo a constantes y variables. En próximos capítulos donde se expongan estructuras de control de flujo, funciones o clases los bloques de código tendrán todo el sentido que se merecen.
Objetivos conseguidos
En este capítulo has aprendido a definir constantes y variables en JS, y a hacerlo siguiendo un conjunto de buenas prácticas que te evitarán muchos dolores de cabeza.
Has aprendido también las normas que aplican al contexto de definición de constantes y variables, y también qué no hacer en lo relativo a contextos y redefiniciones.
Finalmente has visto distintos ejemplos que pueden ejecutarse con node en modo REPL o creando archivos .js.
Próximos pasos
En el próximo capítulo abordaremos los tipos de datos básicos: bool, number y string, algunos de los cuáles hemos visto en los ejemplos de este capítulo.