Continuamos con esta segunda parte de los tutoriales para aprender javascript a nivel básico, ¡vamos con las variables javascript!, abarcando los conceptos más recientes de ECMAScript 6.
Variables javascript
Las variables en programación siguen una lógica similar a las variables que usamos para las matemáticas.
Una variable se utiliza para almacenar y hacer referencia a otro valor.
Al igual que en las matemáticas no se pueden definir ecuaciones y fórmulas complejas sin variables, en programación pasa lo mismo, no se podrían hacer programas potentes sin las variables.
Sin variables, un script que suma dos números podría escribirse como:
1 |
resultado = 2 + 3 |
El script de arriba no sirve de mucho, ya que sólo sirve para el caso en el que el primer elemento de la suma sea el 2 y el segundo elemento sea 3. En cualquier otro caso, el script obtiene un resultado incorrecto.
No obstante, el programa se puede rehacer usando variables para guardar y referirnos a cada número:
1 2 3 |
n_1 = 2 n_2 = 3 resultado = n_1 + n_2 |
Los elementos n_1
y n_2
son variables que almacenan los valores que utiliza el programa. El resultado se calcula siempre en función del valor almacenado por las variables, por lo que este script funciona correctamente para cualquier par de números indicado. Si se modifica el valor de las variables n_1
y n_2
, el script sigue funcionando correctamente.
Declaraciones de las variables
Hay tres tipos de declaraciones en javascript:
1) Con la palabra reservada var
Esta sintaxis puede ser usada para declarar tanto variables locales como globales (más adelante lo explicamos).
El ejemplo anterior se puede realizar en JavaScript de la siguiente manera:
1 2 3 |
var n_1 = 2; var n_2 = 3; var resultado = n_1 + n_2; |
La palabra reservada var
se debe indicar solamente al definir por 1ª vez la variable, a esto se le llama declarar una variable. Cuando se utilizan las variables en el resto del script, solamente es necesario indicar su nombre.
En el ejemplo anterior estaría MAL hacerlo así:
1 2 3 |
var n_1 = 3; var n_2 = 1; var resultado = var n_1 + var n_2; |
Cuando declaramos una variable y le asignamos un valor, se dice que la variable ha sido inicializada.
En JavaScript no es obligatorio inicializar las variables, ya que se pueden declarar por un lado y asignarles un valor posteriormente.
Por ejemplo el código anterior se puede hacer de esta otra forma:
1 2 3 4 5 6 7 |
var n_1; var n_2; n_1 = 3; n_2 = 1; var resultado = n_1 + n_2; |
Una variable declarada usando var o let sin asignarle un valor inicial tiene el valor undefined.
La variable resultado
no está declarada, por lo que JavaScript crea una variable global (más adelante lo explico) y le asigna el valor correspondiente.
De la misma forma, también sería correcto el siguiente código:
1 2 3 |
n_1 = 3; n_2 = 1; resultado = n_1 + n_2; |
En cualquier caso, se recomienda declarar todas las variables que se vayan a utilizar.
2) Con la palabra reservada let
(novedad de ECMAScript6)
Esto se explica más abajo. Ya que primero es necesario que comprendas el concepto de ámbito de las variables.
3) Con la palabra reservada const
(novedad de ECMAScript6)
La palabra reservada const se usa para declarar constantes en JavaScript.
Antes de javascript6 los programadores se veían obligados a crear unas «pseudo constantes» estableciendo el nombre de la variable en mayúscula: var NOMBRE_CONSTANTE.
Y por supuesto, dando por hecho que nadie modificará esa variable posteriormente, algo que se podía hacer sin problemas en JavaScript 5.
Ahora con const (y como debe ser en las constantes), ya no variará el propio valor por mucho que se intente modificar.
Por ejemplo:
1 2 3 4 5 6 7 |
// x: constante const x = 30; console.log(x); // 30 x = 1; console.log(x); // 30 // No cambia el valor de x, sigue siendo 30 |
Recuerda que no puedes declarar una constante con el mismo nombre que una función o que una variable en el mismo ámbito:
1 2 3 4 5 6 7 8 9 |
// Esto dará error function miFuncion() {}; const miFuncion = 5; // Esto también te dará error function miFuncion() { const miVariable = 5; var miVariable; } |
Ámbito / scope de una variable
Las variables tienen un ámbito o scope en inglés (su alcance, contexto) . En resumen es la zona de la aplicación donde se define la variable y la visibilidad que tiene ésta.
El contexto al que se asocian las variables puede parecer bastante arbitrario en JavaScript… ¡sobre todo si vienes de Java!
Por defecto, cuando definimos una variable con la palabra reservada var, su visibilidad viene marcada por la ‘closure’ (function(){…}), en que se encuentra.
Y las closures en este lenguaje las delimitan las funciones.
1 2 3 4 5 6 7 |
function foo () { var bar = 'Hola Mundo'; console.info( bar ); // Hola Mundo } console.info( bar ); // ReferenceError: bar is not defined |
Como puedes ver, si preguntamos por bar dentro de la función la consola nos devuelve el valor correspondiente. Si lo hacemos desde fuera, obtenemos un error por no estar definida la variable.
Nada nuevo bajo el Sol, sin embargo este otro caso puede no ser tan familiar para ciertos desarrolladores:
1 2 3 4 5 |
for( var x = 0; x < 100; x++ ) { // Algo de código por aquí... } console.info( x ); // 100 |
En el ejemplo de arriba, la variable x que hemos usado como contador, trasciende más allá del bucle para continuar existiendo fuera de él. En términos de Javascript tiene sentido ya que como hemos dicho, las closures, las marcan las funciones y en un bucle for no hay función. Sin embargo, desde un punto de vista de arquitectura del software, no tiene lógica que la variable x del bucle siga existiendo más allá de éste, contaminando el contexto global. Eso veremos como combatirlo con let.
Para simplificar, diremos que en javascript tenemos variables globales o locales:
Variables globales
Una variable global (javascript global variable) sería aquella que declaramos fuera de una función (fuera del ámbito), porque está disponible para cualquier otra parte del código y se puede usar en toda la aplicación.
Ejemplo de variable global:
1 2 3 4 5 6 7 |
var nombre = "Ash"; console.log(nombre); function nombre() { console.log(nombre); //Ash } |
A una variable global puede accederse desde el contexto de la aplicación y también desde cualquier función.
Variables locales
Una variable local es la que declaramos dentro de una función (pertenece a un ámbito que no es el global), se llama así porque solo está disponible dentro de la función, es decir, sólo puede accederse a ella desde el contexto de ese ámbito.
Ejemplo de lo que pasa si queremos usar una variable local en el ámbito global del programa:
1 2 3 4 5 6 7 |
function tuPokemon() { var pokemon = "Pikachu"; console.log(pokemon); } tuPokemon();//Pikachu console.log(pokemon); //Uncaught ReferenceError: ap is not defined |
Para que poder acceder a una variable dentro de una función desde el scope global, debemos crear esta variable sin la palabra reservada var:
1 2 3 4 5 6 7 |
function tuPokemon() { pokemon= "Pikachu"; console.log(pokemon); } tuPokemon();//Pikachu console.log(usuario); //Pikachu |
Reglas para declarar el nombre de una variable (identificador)
El nombre de una variable es único y se le conoce como identificador. Debe cumplir estas normas:
- Pueden contener letras, dígitos, guiones y el símbolo del dólar ($)
- Deben comenzar con una letra
- También pueden comenzar por $ y _(guión bajo)
- Se diferencia mayúsculas y minúsculas
- No se pueden usar palabras reservadas como nombre de variable
Por tanto, las siguientes variables tienen nombres correctos:
1 2 3 4 |
var $numero1; var _$letra; var $$$otroNumero; var $_a__$4; |
Por otro, las siguientes variables tienen identificadores incorrectos:
1 2 |
var 1numero; // Empieza por un número var numero;1_123; // Contiene un carácter ";" |
Controlando el scope de las variables declarándolas con let
Como explicamos antes, en los bucles o condiciones, podemos declarar variables temporales y serán visibles desde fuera de esa sentencia.
Observa este código de abajo:
1 2 3 4 |
if (true) { var x = 5; } console.log(x); // 5 |
Como puedes ver, si declaramos una variable dentro de una sentencia de bloque (un bucle for o un condicional if por ejemplo) se puede acceder desde fuera globalmente a esta variable, al contrario de lo que ocurre cuando declaramos esa variable dentro de una función (function).
Este comportamiento cambia, cuando usamos la declaración let introducida en ECMAScript 6.
1 2 3 4 |
if (true) { let y = 5; } console.log(y); // undefined |
Con let
declaramos variables para controlar mejor su propagación. En principio es bastante simple de entender, simplemente evita que una variable sea visible cuando no debe como ocurre con var
.
let permite asignar valor a nuestras variables con visibilidad / validez únicamente dentro del contexto (llaves {}) en el que se ha definido.
Esto significa tanto una mejor optimización del código como un uso más eficiente del recolector de basura del intérprete Javascript.
Trucos y posibilidades de declarar variables
Realizando múltiples declaraciones
Tanto con var como con let podemos encadenar múltiples asignaciones de variables separándolas por comas
1 2 3 4 5 6 7 8 |
{ let foo = 'Hola, hola', bar = 'Adiós, adiós'; console.info( foo, bar ); } console.info( foo, bar ); |
Declaraciones a prueba de bomba
Dado que en Javascript se puede asignar como valor cualquier otro objeto, todo lo que sigue a continuación es perfectamente válido:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
{ var // A primitive fooPrimitive = new Boolean( true ), // A falsy value fooFalsy = null, // An array fooArr = [ 'Hello World', 'Goodbye Lenin' ], // An object fooObj = { keyOne: 'value', keyTwo: 'value' }, // A constructor FooConstructor = function () { this.foo = 'paramOne'; this.bar = 'paramTwo'; }, // An immediately-Invoked Function Expression fooIIFE = ( function () { let foo = function () { console.info( 'Hello from fooIIFE' ); }; return { foo: foo } } )(); console.info( fooPrimitive, fooFalsy, fooArr, fooObj, new FooConstructor(), fooIIFE.foo() ); } |
Prioridad de las declaraciones
Una variable definida dentro de un contexto con let tiene preferencia sobre una variable externa con igual nombre:
1 2 3 4 5 6 7 8 9 |
var jedi = 'Yoda'; if ( jedi ) { let jedi = 'Luke'; console.info( jedi ); // 'Luke' } console.info( jedi ); // 'Yoda' |
Aquí vemos que aunque la variable ‘jedi’ se ha definido fuera del bloque if como global, al redefinirse dentro de su contexto léxico con let, su nuevo valor tiene preferencia. Una vez salimos de las llaves, volvemos a su valor dentro del contexto global.
Una última curiosidad: el Hoisting
Las variables JavaScript pueden hacer referencia a una variable declarada más tarde, sin obtener un error. Este concepto es conocido como hoisting, es decir, una variable declarada se «eleva» o «sube» a la parte superior de la función (closure) en la que se encuentra, independientemente de donde la declaremos:
1 2 3 4 5 6 7 |
var miFuncion = function () { console.log( saludo ); var saludo = 'Hola, holita vecinito'; } miFuncion(); // undefined |
Fijaros, aunque imprimo la variable ‘saludo’ antes de declararla, Javascript no da un error indicando que la variable no está definida, sino que reporta que no tiene valor… Esto es así porque, por detrás, el intérprete está reescribiendo el código anterior de esta manera:
1 2 3 4 5 6 7 8 |
var miFuncion = function () { var saludo; console.log( saludo ); saludo = 'Hola, holita vecinito'; } miFuncion(); // undefined |
Javascript «se fija» en que hay una declaración de una variable dentro de la función y, antes de ejecutarla, «eleva» o sube la declaración de esta variable hasta arriba del todo, aunque no le dé el valor hasta que llegue al punto del código en el que nosotros indicamos la declaración. Por eso, cuando el console pregunta por saludo, realmente si está definida, aunque no tiene valor. Esta peculiar forma de actuar de Javascript es lo que llamamos Hoisting.
¿Y qué pasa si uso let para declarar la variable? Pues que el hoisting se conserva con let continuamos teniendo este fenómeno.
Bueno, esto es todo lo que podemos decir de las variables javascript, si consideras que se puede añadir o corregir algo no dudes en aportarlo con un comentario. Nos vemos en la tercera entrega de JavaScript desde cero.
Estupendo post 🙂 Es fundamental tener estos conceptos claros cuando programas en JS y nunca está de más repasarlos 😉
En mi caso, intento utilizar siempre el modo estricto de JavaScript y declarar siempre las variables, lo cual te puede ahorrar quebraderos de cabeza. Así como utilizar camelcase para nombrar las variables. Y, si el proyecto lo permite, facilitarnos la vida usando let y const.
Un saludo!
Gracias Emilio, y haces bien en trabajar así, a la hora de abordar un proyecto grande o pequeño es buena práctica ponerte tú mismo los límites en javascript 😀
La flexibilidad de este lenguaje puede llevar al «lado oscuro» de las malas prácticas.
Un saludo!
UNa joya de artículo, muchas gracias por dedicar tu tiempo a este curso y no irte por la fácil o lo más breve, MIL GRACIAS!!
Muy claro el concepto de hoisting
Muchas gracias por este Tutorial, muy bien explicado