Las variables son una estructura de datos que asigna un nombre representativo a un valor. Pueden contener datos de cualquier tipo.
El nombre de una variable se denomina identificador. Un identificador válido debe seguir estas reglas:
- Los identificadores pueden contener letras Unicode, símbolos de dólar ($), caracteres de guion bajo (_), dígitos (0-9) y hasta algunos caracteres Unicode.
- Los identificadores no pueden contener espacios en blanco, ya que el analizador usa espacios en blanco para separar los elementos de entrada. Por ejemplo, si intentas llamar a una variable
my Variable
en lugar demyVariable
, el analizador ve dos identificadores,my
yVariable
, y arroja un error de sintaxis ("token inesperado: identificador"). Los identificadores deben comenzar con una letra, un guion bajo (
_
) o un signo de dólar ($
). Para evitar confusiones entre números y identificadores, no pueden comenzar con dígitos:let 1a = true; > Uncaught SyntaxError: Invalid or unexpected token
Si JavaScript permitiera números al comienzo de un identificador, se permitirían identificadores que solo contengan números, lo que provocaría conflictos entre los números que se usan como números y los que se usan como identificadores:
let 10 = 20 10 + 5 > ?
Las "palabras reservadas" que ya tienen significado sintáctico no se pueden usar como identificadores.
Los identificadores no pueden contener caracteres especiales (
! . , / \ + - * =
).
Las siguientes no son reglas estrictas para crear identificadores, pero son prácticas recomendadas de la industria que facilitan el mantenimiento de tu código. Si tu proyecto específico tiene estándares diferentes, sigue esos estándares para mantener la coherencia.
Siguiendo el ejemplo establecido por los métodos y las propiedades integrados de JavaScript, el mayúsculas y minúsculas intercaladas (también estilizado como “camelCase”) es una convención muy común para los identificadores que constan de varias palabras. El estilo de escritura CamelCase consiste en escribir en mayúscula la primera letra de cada palabra, excepto la primera, para mejorar la legibilidad sin espacios.
let camelCasedIdentifier = true;
Algunos proyectos usan otras convenciones de nombres según el contexto y la naturaleza de los datos. Por ejemplo, la primera letra de una clase suele escribirse en mayúsculas, por lo que los nombres de clases de varias palabras suelen usar una variante de mayúsculas y minúsculas, comúnmente llamada “mayúsculas y minúsculas” o Pascal.
class MyClass {
}
Los identificadores deben describir de forma concisa la naturaleza de los datos que contienen (por ejemplo, currentMonthDays
es un nombre mejor que theNumberOfDaysInTheCurrentMonth
) y deben leerse con claridad de un vistazo (originalValue
es mejor que val
). Los identificadores myVariable
que se usan en todo este módulo funcionan en el contexto de ejemplos aislados, pero no serían muy útiles en el código de producción porque no proporcionan información sobre los datos que contienen.
Los identificadores no deben ser demasiado específicos sobre los datos que contienen, ya que sus valores pueden cambiar según la forma en que las secuencias de comandos actúan sobre esos datos o las decisiones que tomen los futuros responsables del mantenimiento. Por ejemplo, es posible que una variable a la que se le asignó originalmente el identificador miles
deba cambiarse a un valor en kilómetros más adelante en el proyecto, lo que requiere que los responsables del mantenimiento cambien cualquier referencia a esa variable para evitar confusiones en el futuro. Para evitar esto, usa distance
como identificador.
JavaScript no otorga ningún privilegio ni significado especial a los identificadores que comienzan con caracteres de guion bajo (_
), pero suelen usarse para mostrar que una variable, un método o una propiedad es "privada", lo que significa que solo está destinada a usarse dentro del contexto del objeto que la contiene y no se debe acceder a ella ni modificarla fuera de ese contexto. Esta es una convención que se heredó de otros lenguajes de programación y es anterior a la adición de las propiedades privadas de JavaScript.
Declaración de una variable
Existen varias formas de hacer que JavaScript conozca un identificador, un proceso que se denomina “declarar” una variable. Una variable se declara con las palabras clave let
, const
o var
.
let myVariable;
Usa let
o var
para declarar una variable que se pueda cambiar en cualquier momento. Estas
palabras clave le indican al intérprete de JavaScript que una cadena de caracteres es un
identificador que podría contener un valor.
Cuando trabajes en una base de código moderna, usa let
en lugar de var
. var
aún funciona en navegadores modernos, pero tiene algunos comportamientos poco intuitivos que se definieron en las versiones más antiguas de JavaScript y que no se pudieron cambiar más adelante para preservar la retrocompatibilidad. Se agregó let
en ES6 para abordar algunos problemas con el diseño de var
.
Para inicializar una variable declarada, se le asigna un valor. Usa un solo signo igual (=
) para asignar o reasignar un valor a una variable. Puedes hacerlo como parte de la misma sentencia que lo declara:
let myVariable = 5;
myVariable + myVariable
> 10
También puedes declarar una variable con let
(o var
) sin inicializarla de inmediato. Si lo haces, el valor inicial de la variable será undefined
hasta que el código le asigne un valor.
let myVariable;
myVariable;
> undefined
myVariable = 5;
myVariable + myVariable
> 10
Una variable con un valor undefined
es diferente de una variable no definida cuyo identificador aún no se declaró. Si haces referencia a una variable que no declaraste, se generará un error.
myVariable
> Uncaught ReferenceError: myVariable is not defined
let myVariable;
myVariable
> undefined
La asociación de un identificador con un valor se denomina, por lo general, “vinculación”.
La sintaxis que sigue a las palabras clave let
, var
o const
se denomina "lista de vinculación" y permite varias declaraciones de variables separadas por comas (que terminan con el punto y coma esperado). Esto hace que los siguientes fragmentos de código sean funcionalmente idénticos:
let firstVariable,
secondVariable,
thirdVariable;
let firstVariable;
let secondVariable;
let thirdVariable;
La reasignación del valor de una variable no usa let
(ni var
), porque JavaScript ya sabe que la variable existe:
let myVariable = true;
myVariable
> true
myVariable = false;
myVariable
> false
Puedes volver a asignar valores nuevos a las variables en función de sus valores existentes:
let myVariable = 10;
myVariable
> 10
myVariable = myVariable * myVariable;
myVariable
> 100
Si intentas volver a declarar una variable con let
en un entorno de producción,
recibirás un error de sintaxis:
let myVariable = true;
let myVariable = false;
> Uncaught SyntaxError: redeclaration of let myVariable
Las herramientas para desarrolladores de los navegadores son más permisivas con la redeclaración de let
(y class
), por lo que es posible que no veas el mismo error en la consola para desarrolladores.
Para preservar la compatibilidad con navegadores heredados, var
permite la nueva declaración innecesaria sin errores en cualquier contexto:
var myVariable = true;
var myVariable = false;
myVariable\
> false
const
Usa la palabra clave const
para declarar una constante, un tipo de variable que se debe inicializar de inmediato y que, luego, no se puede cambiar. Los identificadores de constantes
siguen todas las mismas reglas que las variables declaradas con let
(y var
):
const myConstant = true;
myConstant
> true
No puedes declarar una constante sin asignarle un valor de inmediato, ya que las constantes no se pueden volver a asignar después de crearlas, por lo que cualquier constante no inicializada permanecerá como undefined
para siempre. Si intentas declarar una constante sin inicializarla, se muestra un error de sintaxis:
const myConstant;
Uncaught SyntaxError: missing = in const declaration
Si intentas cambiar el valor de una variable declarada con const
de la misma manera que podrías cambiar el valor de una variable declarada con let
(o var
), se produce un error de tipo:
const myConstant = true;
myConstant = false;
> Uncaught TypeError: invalid assignment to const 'myConstant'
Sin embargo, cuando una constante se asocia con un objeto, las propiedades de ese objeto pueden alterarse.
const constantObject = { "firstvalue" : true };
constantObject
> Object { firstvalue: true }
constantObject.secondvalue = false;
constantObject
> Object { firstvalue: true, secondvalue: false }
Una constante que contiene un objeto es una referencia inmutable a un valor de datos mutable. Si bien no se puede cambiar la constante, se pueden alterar, agregar o quitar las propiedades del objeto al que se hace referencia:
const constantObject = { "firstvalue" : true };
constantObject = false
> Uncaught TypeError: invalid assignment to const 'constantObject'
Cuando no esperas que se reasigne una variable, se recomienda que la hagas
una constante. El uso de const
le indica a tu equipo de desarrollo o a los futuros encargados del mantenimiento de un proyecto que no cambien ese valor para evitar romper las suposiciones que hace tu código sobre cómo se usa, por ejemplo, que una variable se evaluará en función de un tipo de datos esperado.
Alcance de la variable
El alcance de una variable es la parte de una secuencia de comandos en la que está disponible.
Fuera del alcance de una variable, no se definirá, no como un identificador que contiene un valor undefined
, sino como si no se hubiera declarado.
Según la palabra clave que uses para declarar una variable y el contexto en el que la definas, puedes asignar variables a instrucciones de bloqueo (alcance de bloque), funciones individuales (alcance de función) o a toda la aplicación de JavaScript (alcance global).
Alcance del bloque
Cualquier variable que declares con let
o const
se centra en su sentencia de bloque más cercana, lo que significa que solo se puede acceder a la variable dentro de ese bloque. Intentar acceder a una variable centrada en un bloque fuera de su bloque contenedor genera el mismo error que intentar acceder a una variable que no existe:
{
let scopedVariable = true;
console.log( scopedVariable );
}
> true
scopedVariable
> ReferenceError: scopedVariable is not defined
En lo que respecta a JavaScript, una variable centrada en un bloque no existe fuera del bloque que la contiene. Por ejemplo, puedes declarar una constante dentro de un bloque y, luego, declarar otra constante fuera de ese bloque que use el mismo identificador:
{
const myConstant = false;
}
const myConstant = true;
scopedConstant;
> true
Aunque una variable declarada no se puede extender a su bloque superior, está disponible para todos los bloques secundarios:
{
let scopedVariable = true;
{
console.log( scopedVariable );
}
}
> true
El valor de una variable declarada se puede cambiar desde un bloque descendiente:
{
let scopedVariable = false;
{
scopedVariable = true;
}
console.log( scopedVariable );
}
> true
Una variable nueva se puede inicializar con let
o const
dentro de un bloque descendente sin errores, incluso si usa el mismo identificador que una variable en un bloque superior:
{
let scopedVariable = false;
{
let scopedVariable = true;
}
console.log( scopedVariable );
}
> false
Alcance de la función
Las variables declaradas con var
tienen su alcance en la función contenedora más cercana (o en el bloque de inicialización estática dentro de una clase).
function myFunction() {
var scopedVariable = true;
return scopedVariable;
}
scopedVariable;
> ReferenceError: scopedVariable is not defined
Esto sigue siendo así después de que se llama a una función. Aunque la variable se inicializa mientras se ejecuta la función, esta variable aún no está disponible fuera del alcance de la función:
function myFunction() {
var scopedVariable = true;
return scopedVariable;
}
scopedVariable;
> ReferenceError: scopedVariable is not defined
myFunction();
> true
scopedVariable;
> ReferenceError: scopedVariable is not defined
Alcance global
Una variable global está disponible en toda una aplicación de JavaScript, dentro de todos los bloques y funciones, para cualquier secuencia de comandos de la página.
Si bien esto puede parecer un valor predeterminado deseable, las variables a las que puede acceder y modificar cualquier parte de una aplicación pueden agregar una sobrecarga innecesaria o incluso provocar colisiones con variables en otra parte de una aplicación con el mismo identificador. Esto se aplica a todo JavaScript involucrado en la renderización de una página, incluso elementos como bibliotecas de terceros y estadísticas del usuario. Por lo tanto, se recomienda evitar contaminar el alcance global siempre que sea posible.
Cualquier variable declarada con var
fuera de una función superior, o con let
o const
fuera de un bloque superior, es global:
var functionGlobal = true; // Global
let blockGlobal = true; // Global
{
console.log( blockGlobal );
console.log( functionGlobal );
}
> true
> true
(function() {
console.log( blockGlobal );
console.log( functionGlobal );
}());
> true
> true
Asignar un valor a una variable sin declararla de forma explícita (es decir, nunca usar var
, let
o const
para crearla) eleva una variable al alcance global, incluso cuando se inicializa dentro de una función o un bloque. A veces, una variable creada con este patrón se denomina “global implícita”.
function myFunction() {
globalVariable = "global";
return globalVariable
}
myFunction()\
> "global"
globalVariable\
> "global"
Elevación de variables
Las variables y las declaraciones de funciones se elevan a la parte superior de su alcance, lo que significa que el intérprete de JavaScript procesa cualquier variable declarada en cualquier punto de una secuencia de comandos y la mueve de manera efectiva a la primera línea de su alcance envolvente antes de ejecutarla. Esto significa que se puede hacer referencia a una variable declarada con var
antes de que se declare sin encontrar un error:
hoistedVariable
> undefined
var hoistedVariable;
Debido a que solo se aloja la declaración de la variable, no la inicialización, las variables que no se declararon explícitamente con var
, let
o const
no se elevan:
unhoistedVariable;
> Uncaught ReferenceError: unhoistedVariable is not defined
unhoistedVariable = true;
Como se mencionó anteriormente, a una variable declarada, pero no inicializada, se le asigna un valor de undefined
. Ese comportamiento también se aplica a las declaraciones de variables elevadas, pero solo a aquellas declaradas con var
.
hoistedVariable
> undefined
var hoistedVariable = 2 + 2;
hoistedVariable\
> 4
Este comportamiento poco intuitivo es en gran medida un remanente de las decisiones de diseño que se tomaron en las primeras versiones de JavaScript y no se puede cambiar sin correr el riesgo de dañar los sitios existentes.
let
y const
abordan este comportamiento arrojando un error cuando se accede a una variable antes de que se cree:
{
hoistedVariable;
let hoistedVariable;
}
> Uncaught ReferenceError: can't access lexical declaration 'hoistedVariable' before initialization
Este error es diferente del error "hoistedVariable is not defined" que podrías esperar cuando intentas acceder a una variable no declarada. Debido a que JavaScript
elevó la variable, sabe que se creará dentro
del alcance determinado. Sin embargo, en lugar de hacer que esa variable esté disponible antes de su declaración con un valor de undefined
, el intérprete muestra un error.
Se dice que las variables declaradas con let
o const
(o class
) existen en una "zona muerta temporal" ("TDZ") desde el comienzo de su bloque envolvente hasta el punto del código en el que se declara la variable.
La zona muerta temporal hace que el comportamiento de let
sea más intuitivo que el de var
para los autores. También es fundamental para el diseño de const
. Debido a que las constantes no se pueden
cambiar, una constante elevada a la parte superior de su alcance y a la que se le asignó un valor implícito
de undefined
no se podría inicializar con un valor significativo.
Verifica tu comprensión
¿Con qué tipos de caracteres puedes iniciar un identificador?
¿Cuál es el método preferido para declarar una variable cuyo valor se puede cambiar en cualquier momento?