As variáveis são uma estrutura de dados que atribui um nome representativo a um valor. Eles podem conter dados de qualquer tipo.
O nome de uma variável é chamado de identificador. Um identificador válido precisa seguir estas regras:
- Os identificadores podem conter letras Unicode, cifrões ($), sublinhados (_), dígitos (0-9) e até mesmo alguns caracteres Unicode.
- Os identificadores não podem conter espaços em branco, porque o analisador usa espaços em branco para
separar elementos de entrada. Por exemplo, se você tentar chamar uma variável
my Variable
em vez demyVariable
, o analisador vai encontrar dois identificadores,my
eVariable
, e gerar um erro de sintaxe ("token inesperado: identificador"). Os identificadores precisam começar com uma letra, sublinhado (
_
) ou cifrão ($
). Eles não podem começar com dígitos para evitar confusão entre números e identificadores:let 1a = true; > Uncaught SyntaxError: Invalid or unexpected token
Se o JavaScript permitisse números no início de um identificador, isso permitiria identificadores compostos apenas por números, causando conflitos entre números usados como números e números usados como identificadores:
let 10 = 20 10 + 5 > ?
Palavras reservadas que já têm significado sintático não podem ser usadas como identificadores.
Os identificadores não podem conter caracteres especiais (
! . , / \ + - * =
).
As regras a seguir não são rígidas para a criação de identificadores, mas são práticas recomendadas do setor que facilitam a manutenção do código. Se o projeto específico tiver padrões diferentes, siga esses padrões para manter a consistência.
Seguindo o exemplo definido pelos métodos e propriedades integrados do JavaScript, o formato came case (também estilizado como "camelCase") é uma convenção muito comum para identificadores compostos por várias palavras. A concatenação é a prática de colocar em maiúscula a primeira letra de cada palavra, exceto a primeira, para melhorar a legibilidade sem espaços.
let camelCasedIdentifier = true;
Alguns projetos usam outras convenções de nomenclatura, dependendo do contexto e da natureza dos dados. Por exemplo, a primeira letra de uma classe normalmente é maiúscula, então os nomes de classes com várias palavras geralmente usam uma variante de letras maiúsculas concatenadas, comumente chamada de "letras maiúsculas concatenadas" ou Pascal.
class MyClass {
}
Os identificadores precisam descrever de forma concisa a natureza dos dados que contêm (por
exemplo, currentMonthDays
é um nome melhor do que theNumberOfDaysInTheCurrentMonth
)
e ser lidos claramente de relance (originalValue
é melhor do que val
). Os
identificadores myVariable
usados neste módulo funcionam no contexto de
exemplos isolados, mas não seriam úteis no código de produção porque não
fornecem informações sobre quais dados eles contêm.
Os identificadores não podem ser muito específicos sobre os dados que contêm, porque
os valores podem mudar dependendo de como os scripts agem nesses dados ou das
decisões tomadas pelos mantenedores no futuro. Por exemplo, uma variável que recebeu originalmente o
identificador miles
pode precisar ser alterada para um valor em quilômetros mais tarde
no projeto, exigindo que os mantenedores mudem todas as referências a essa variável para
evitar confusão no futuro. Para evitar isso, use distance
como seu identificador.
O JavaScript não dá nenhum privilégio ou significado especial a identificadores que
começam com caracteres de sublinhado (_
), mas eles geralmente são usados para mostrar que
uma variável, um método ou uma propriedade é "privada", o que significa que ela é destinada
apenas ao uso no contexto do objeto que a contém e não pode ser
acessada ou modificada fora desse contexto. Essa é uma convenção transferida
de outras linguagens de programação e antecede a adição das propriedades privadas do JavaScript.
Declaração de variável
Há várias maneiras de informar o JavaScript sobre um identificador, um processo
chamado de "declaração" de uma variável. Uma variável é declarada usando as palavras-chave let
, const
ou var
.
let myVariable;
Use let
ou var
para declarar uma variável que pode ser mudada a qualquer momento. Essas
palavras-chave informam ao interpretador JavaScript que uma string de caracteres é um
identificador que pode conter um valor.
Ao trabalhar em uma base de código moderna, use let
em vez de var
. var
ainda funciona
em navegadores modernos, mas tem alguns comportamentos não intuitivos que foram definidos nas
versões mais antigas do JavaScript e não puderam ser alterados mais tarde para
preservar a compatibilidade com versões anteriores. let
foi adicionado no ES6 para resolver alguns problemas
com o design de var
.
Uma variável declarada é inicializada atribuindo um valor a ela. Use um
sinal de igual (=
) para atribuir ou reatribuir um valor a uma variável. Você pode fazer
isso como parte da mesma instrução que a declara:
let myVariable = 5;
myVariable + myVariable
> 10
Também é possível declarar uma variável com let
(ou var
) sem inicializá-la
imediatamente. Se você fizer isso, o valor inicial da variável será undefined
até que o
código atribua um valor a ela.
let myVariable;
myVariable;
> undefined
myVariable = 5;
myVariable + myVariable
> 10
Uma variável com um valor undefined
é diferente de uma variável indefinida
cujo identificador ainda não foi declarado. Fazer referência a uma variável que você não
declarou causa um erro.
myVariable
> Uncaught ReferenceError: myVariable is not defined
let myVariable;
myVariable
> undefined
A associação de um identificador a um valor geralmente é chamada de "vinculação".
A sintaxe que segue as palavras-chave let
, var
ou const
é chamada de
"lista de vinculação" e permite várias declarações de variáveis separadas por vírgulas
(que terminam com o ponto e vírgula esperado). Isso torna os seguintes snippets de código
funcionalmente idênticos:
let firstVariable,
secondVariable,
thirdVariable;
let firstVariable;
let secondVariable;
let thirdVariable;
Reatribuir o valor de uma variável não usa let
(ou var
), porque o JavaScript
já sabe que a variável existe:
let myVariable = true;
myVariable
> true
myVariable = false;
myVariable
> false
É possível reatribuir novos valores às variáveis com base nos valores atuais:
let myVariable = 10;
myVariable
> 10
myVariable = myVariable * myVariable;
myVariable
> 100
Se você tentar declarar novamente uma variável usando let
em um ambiente de produção,
vai receber um erro de sintaxe:
let myVariable = true;
let myVariable = false;
> Uncaught SyntaxError: redeclaration of let myVariable
As ferramentas para desenvolvedores dos navegadores
são mais permissivas em relação à rededicação de let
(e class
). Portanto, talvez você não
encontre o mesmo erro no console do desenvolvedor.
Para preservar a compatibilidade com navegadores legados, o var
permite a redefinição desnecessária
sem erros em qualquer contexto:
var myVariable = true;
var myVariable = false;
myVariable\
> false
const
Use a palavra-chave const
para declarar uma constante, um tipo de variável que precisa ser
inicializada imediatamente e que não pode ser modificada. Os identificadores de constantes
seguem todas as mesmas regras das variáveis declaradas usando let
(e var
):
const myConstant = true;
myConstant
> true
Não é possível declarar uma constante sem atribuir imediatamente um valor a ela, porque
as constantes não podem ser reatribuídas depois de criadas. Portanto, qualquer constante não inicializada
ficará undefined
para sempre. Se você tentar declarar uma constante
sem inicializá-la, vai receber um erro de sintaxe:
const myConstant;
Uncaught SyntaxError: missing = in const declaration
Tentar mudar o valor de uma variável declarada com const
da mesma forma que
você mudaria o valor de uma variável declarada com let
(ou var
) causa um erro de
tipo:
const myConstant = true;
myConstant = false;
> Uncaught TypeError: invalid assignment to const 'myConstant'
No entanto, quando uma constante é associada a um objeto, as propriedades desse objeto podem ser alteradas.
const constantObject = { "firstvalue" : true };
constantObject
> Object { firstvalue: true }
constantObject.secondvalue = false;
constantObject
> Object { firstvalue: true, secondvalue: false }
Uma constante que contém um objeto é uma referência imutável a um valor de dados mutável. Embora a constante não possa ser alterada, as propriedades do objeto referenciado podem ser alteradas, adicionadas ou removidas:
const constantObject = { "firstvalue" : true };
constantObject = false
> Uncaught TypeError: invalid assignment to const 'constantObject'
Quando você não espera que uma variável seja reatribuída, é recomendável torná-la
uma constante. O uso de const
informa à equipe de desenvolvimento ou aos futuros mantenedores de um
projeto que não é necessário mudar esse valor para evitar a quebra das suposições feitas pelo código
sobre como ele é usado. Por exemplo, que uma variável será
avaliada em relação a um tipo de dados esperado.
Escopo de variáveis
O escopo de uma variável é a parte de um script em que ela está disponível.
Fora do escopo de uma variável, ela não será definida, não como um identificador
que contém um valor undefined
, mas como se não tivesse sido declarada.
Dependendo da palavra-chave usada para declarar uma variável e do contexto em que ela é definida, é possível definir o escopo das variáveis para instruções de bloco (escopo de bloco), funções individuais (escopo de função) ou todo o aplicativo JavaScript (escopo global).
Escopo do bloco
Qualquer variável declarada usando let
ou const
tem escopo para a
instrução de bloco mais próxima que a contém,
o que significa que a variável só pode ser acessada dentro desse bloco. Tentar
acessar uma variável com escopo de bloco fora do bloco que a contém causa o mesmo
erro que tentar acessar uma variável que não existe:
{
let scopedVariable = true;
console.log( scopedVariable );
}
> true
scopedVariable
> ReferenceError: scopedVariable is not defined
No JavaScript, uma variável com escopo de bloco não existe fora do bloco que a contém. Por exemplo, é possível declarar uma constante dentro de um bloco e, em seguida, declarar outra constante fora desse bloco que usa o mesmo identificador:
{
const myConstant = false;
}
const myConstant = true;
scopedConstant;
> true
Embora uma variável declarada não possa ser estendida para o bloco pai, ela está disponível para todos os blocos descendentes:
{
let scopedVariable = true;
{
console.log( scopedVariable );
}
}
> true
O valor de uma variável declarada pode ser alterado em um bloco descendente:
{
let scopedVariable = false;
{
scopedVariable = true;
}
console.log( scopedVariable );
}
> true
Uma nova variável pode ser inicializada com let
ou const
dentro de um bloco
descendente sem erros, mesmo que use o mesmo identificador que uma variável em um
bloco pai:
{
let scopedVariable = false;
{
let scopedVariable = true;
}
console.log( scopedVariable );
}
> false
Escopo da função
As variáveis declaradas usando var
têm escopo para a função que as contém mais de perto
(ou o bloco de inicialização estática dentro de uma classe).
function myFunction() {
var scopedVariable = true;
return scopedVariable;
}
scopedVariable;
> ReferenceError: scopedVariable is not defined
Isso ainda acontece depois que uma função é chamada. Mesmo que a variável seja inicializada durante a execução da função, ela ainda não estará disponível fora do escopo da função:
function myFunction() {
var scopedVariable = true;
return scopedVariable;
}
scopedVariable;
> ReferenceError: scopedVariable is not defined
myFunction();
> true
scopedVariable;
> ReferenceError: scopedVariable is not defined
Escopo global
Uma variável global está disponível em todo um aplicativo JavaScript, dentro de todos os blocos e funções, para qualquer script na página.
Embora isso possa parecer um padrão desejável, variáveis que qualquer parte de um aplicativo pode acessar e modificar podem adicionar sobrecarga desnecessária ou até mesmo causar colisões com variáveis em outro lugar de um aplicativo com o mesmo identificador. Isso se aplica a todos os JavaScripts envolvidos na renderização de uma página, incluindo bibliotecas de terceiros e análises de usuários. Portanto, é recomendado evitar poluir o escopo global sempre que possível.
Qualquer variável declarada usando var
fora de uma função pai ou usando let
ou
const
fora de um bloco pai é 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
A atribuição de um valor a uma variável sem declará-la explicitamente (ou seja,
nunca usando var
, let
ou const
para criá-la) eleva uma variável ao
escopo global, mesmo quando inicializada em uma função ou bloco. Uma variável
criada usando esse padrão às vezes é chamada de "global implícita".
function myFunction() {
globalVariable = "global";
return globalVariable
}
myFunction()\
> "global"
globalVariable\
> "global"
Elevação de variáveis
As declarações de variáveis e funções são elevadas para o topo do escopo,
o que significa que o interpretador JavaScript processa qualquer variável declarada em qualquer
ponto de um script e a move para a primeira linha do escopo
antes de executar o script. Isso significa que uma variável declarada usando
var
pode ser referenciada antes de ser declarada sem encontrar um
erro:
hoistedVariable
> undefined
var hoistedVariable;
Como apenas a declaração de variável é hospedada, e não a inicialização,
as variáveis que não foram declaradas explicitamente com var
, let
ou const
não são elevadas:
unhoistedVariable;
> Uncaught ReferenceError: unhoistedVariable is not defined
unhoistedVariable = true;
Como mencionado anteriormente, uma variável declarada, mas não inicializada,
é atribuída a um valor de undefined
. Esse comportamento também se aplica a declarações de variável
elevadas, mas apenas àquelas declaradas usando var
.
hoistedVariable
> undefined
var hoistedVariable = 2 + 2;
hoistedVariable\
> 4
Esse comportamento não intuitivo é uma herança das decisões de design feitas nas versões mais antigas do JavaScript e não pode ser alterado sem o risco de quebrar sites existentes.
let
e const
resolvem esse comportamento gerando um erro quando uma
variável é acessada antes de ser criada:
{
hoistedVariable;
let hoistedVariable;
}
> Uncaught ReferenceError: can't access lexical declaration 'hoistedVariable' before initialization
Esse erro é diferente do erro "hoistedVariable is not defined" que você
pode esperar ao tentar acessar uma variável não declarada. Como o JavaScript
elevou a variável, ele sabe que a variável será criada dentro
do escopo especificado. No entanto, em vez de disponibilizar essa variável antes da declaração com um valor de undefined
, o interpretador gera um erro.
As variáveis declaradas com let
ou const
(ou class
) são consideradas existentes em uma
"zona morta temporal" ("TDZ", na sigla em inglês) desde o início do bloco de contenção até o
ponto no código em que a variável é declarada.
A zona morta temporal torna o comportamento de let
mais intuitivo do que var
para
autores. Ele também é essencial para o design de const
. Como as constantes não podem ser
alteradas, uma constante elevada para o topo do escopo e que recebe um valor implícito
de undefined
não pode ser inicializada com um valor significativo.
Teste seu conhecimento
Com que tipos de caracteres é possível iniciar um identificador?
Qual é o método preferido de declarar uma variável cujo valor possa ser alterado a qualquer momento?