Entendiendo Javascript: Variables (let, var y const)
Variable
Una variable se puede describir como el nombre con el que identificamos un valor, este valor puede ser constante, nunca cambia, como PI que equivale a 3.1415…., o a un valor cambiante como la fecha de nacimiento, cambiará dependiendo de la persona, pero siempre sabes a que se están refiriendo con “fecha de nacimiento”.
En javascript el nombre de una variable, mejor conocido como identificador, debe seguir ciertas reglas, primero debe empezar con una letra (puede ser minúscula o mayúscula, javascript diferencia entre los dos haciendo que hola_mundo sea diferente a Hola_mundo), un guión bajo (_hola), o un signo de dólar ($hola); mientras que los siguientes caracteres pueden incluir letras, guión bajo, signo de dólar, dígitos (0 – 9) y la mayoría de las letras Unicode. Además, el valor de una variable puede ser un primitivo o la referencia a un objeto.
Scope
El alcance, o mas conocido como scope por su traducción al inglés, es todos los lugares en los que la variable está disponible, se llama scope global cuando la variable se encuentra disponible en cualquier parte del documento, suelen ser variables fuera de funciones; mientras que cuando están dentro de una función se le llama scope local, ya que slo esta disponible dentro de esa función. También existe algo llamado scope de bloque donde la variable es local y solo esta disponible dentro de un bloque, se considera bloque a cualquier cosa que se encuentre entre dos corchetes {} o .
En el siguiente código vemos que al intentar mostrar el valor en consola de “y” nos marca un error fuera de la función ya que su scope es local lo cual la delimita a solo estar disponible dentro de la función, y “x” al haber sido declarada fuera la hace una variable global.
var x = 1;
function localScope() {
var y = 2;
console.log(y); // 2
}
localScope();
console.log(x); // 1
console.log(y); // Uncaught ReferenceError: y is not defined
Javascript tiene tres diferentes formas de declarar una variable que son var, const y let, hablemos de cada una:
VAR
Esta forma declara una variable que puede ser inicializada opcionalmente con un valor, esto significa que puedo escribirla como var x
o var x = 1
, y su valor puede ir cambiando durante la ejecución de tu programa. En el siguiente código te muestro como el valor de x cambia imprimiéndole usando console log, usa tu editor favorito y cambia los valores asignados para que veas como cambia lo que se esta mostrando en consola.
var x = 1;
if (x === 1) {
var x = 2;
console.log(x); // expected output: 2
}
console.log(x); // expected output: 2
Cuando var es creada durante hoisting, que es el proceso que realiza javascript antes de ejecutar el código para crear el espacio en memoria de la variable, se le asigna el valor undefined, este valor indica que no se le ha asignado un valor aun o no se ha declarado en absoluto, y este cambiará una vez el código sea ejecutado y encuentre su primera asignación, si nunca se llegara a asignar un valor, por ejemplo en todo el código solo encontramos var x
pero nunca x = algo
, entonces siempre sera undefined.
'use strict';
console.log(x); // undefined (note: not ReferenceError) due to hoisting
var x = 1; // assigns a value
console.log(x); // 1
Ahora hablemos de su scope, var está solo limitado por funciones y módulos, en caso de no estar dentro de estos se dice que tiene un scope global.
'use strict';
function foo() {
var x = 1;
function bar() {
var y = 2;
console.log(x); // 1 (function `bar` closes over `x`)
console.log(y); // 2 (`y` is in scope)
}
bar();
console.log(x); // 1 (`x` is in scope)
console.log(y); // ReferenceError in strict mode, `y` is scoped to `bar`
}
foo();
Las variables declaradas con var pueden ser duplicadas sin obtener un error, incluso usando strict mode, javascript lo reconocerá como si fuera una nueva asignación. En bloques de código muy grandes esto podría causar un error, por eso es que en muchas personas de la comunidad recomiendan el uso de let en su lugar.
var x = 2;
console.log(x) // 2
var x = 3;
console.log(x) // 3 (no error showed)
LET
Esta forma declara una variable que puede ser inicializada opcionalmente con scope de bloque, esto significa que solo existe dentro del bloque o expresión en que fue declarada a diferencia de var que puede existir globalmente o local a una función. Igual que var su valor puede cambiar durante la ejecución.
En el siguiente ejemplo podemos notar como javascript no verá como repetida la declaración de “x” usando let, sino como si fuera una nueva variable que solo existe dentro de ese bloque, por lo tanto let x = 1
no existe aqui ya que fue reemplazada por let x = 2
.
function varTest() {
var x = 1;
{
var x = 2; // same variable!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
{
let x = 2; // different variable
console.log(x); // 2
}
console.log(x); // 1
}
varTest();
letTest();
Al igual que var let es inicializada con undefined si no tiene un valor asignado, pero a diferencia de ésta let no puede crear propiedades en el objeto global o window cuando se declara globalmente.
var x;
let y;
console.log(x); // undefined
console.log(y); // undefined
x = 'global';
y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined
CONST
Esta tiene un valor de bloque igual que let, es constante por lo que su valor no puede cambiar ni ser declarado otra vez y siempre tiene que ser inicializada con un valor.
const FOO; // Uncaught SyntaxError: Missing initializer in const declaration
const number = 42;
try {
number = 99;
} catch (err) {
console.log(err);
// expected output: TypeError: invalid assignment to const `number'
// Note - error messages will vary depending on browser
}
console.log(number); // expected output: 42
Aunque no se puede reasignar, const tiene el comportamiento de que si se le asigna un objeto o un array, se pueden cambiar sus propiedades.
const objectExample = { a: 3, b: 2, c: 1};
console.log(objectExample); // { a: 3, b: 2, c: 1}
objectExample.b = 3;
console.log(objectExample); // { a: 3, b:3, c: 1}
objectExample = { other: 'value' }; // Uncaught TypeError: Assignment to constant variable.
const arrayExample = [];
arrayExample.push('a'); // ["a"]
arrayExample = ['b']; // Uncaught TypeError: Assignment to constant variable.
Teniendo en cuenta que const solo existe dentro de un bloque, esta no puede ser usada sola dentro de uno, ya que no habrá forma de acceder a ella fuera de este.
if (true) const a = 1; // SyntaxError: Unexpected token 'const'
Otras formas de declarar variables
Otras veces encontraras variables declaradas de forma diferente a las que te mostré arriba, así que vamos a explicarlas.
Destructuring
Te ayuda a obtener una propiedad en específico de un objeto o array asignandolo a una nueva variable. Checa los siguientes ejemplos:
const foo = { bar:10, baz:12 }
const { bar } = foo;
console.log(bar); // 10
const gg = ['23', 34];
const [ num1, num2 ] = gg;
console.log(num2); // 34
Incluso podemos usar let o var y así podemos cambiar el valor de la nueva variable sin afectar el objeto original.
const foo = { bar:10, baz:12 }
let { bar } = foo;
console.log(bar); // 10
bar = 35;
console.log(foo); // { bar: 10, baz: 12 }
console.log(bar); // 35
Variables no declaradas o implícitas
Para entender la creación de este tipo de variables debemos entender como funciona el scope global. Cuando tu creas una variable con scope global en javascript esta se agrega al objeto de nombres de variables del objeto global, este no puede ser cambiado ni borrado, y tiene la ventaja de poder usarlo en cualquier scope sin la necesidad de usar globalThis. o window. o global..
Si tu quisieras declarar una variable global podrías hacer lo siguiente:
foo = 'f' // In non-strict mode
Object.hasOwn(globalThis, 'foo') // true
Esto cambió en ECMAScript 5, la asignación usando strict mode resultará en un ReferenceError, se hizo para evitar la creación accidental de propiedades en el objeto global. Por lo tanto no es que existan variables implícitas, simplemente javascript tiene esta forma de agregar variables al objeto global.