Escopo de Variáveis - JavaScript
Todas as variáveis e constantes em JavaScript têm um escopo definido dentro do qual elas podem operar.
Variáveis globais
Todas as variáveis e constantes que são declaradas fora das funções são globais:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Programício</title>
</head>
<body>
<script>
var x = 5;
let y = 8;
const z = 9;
function displaySum() {
var sum = x + y + z;
console.log(sum);
}
displaySum(); // 22
</script>
</body>
</html>
Aqui, as variáveis x
y
z
No entanto, a variável sum
Definindo o escopo local
Para definir um escopo local em JavaScript, usa-se chaves { }
{
var x = 5;
let y = 8;
const z = 9;
}
No entanto, nesse caso, o comportamento da variável depende de como ela é definida (através de var
let
var
let
const
Variáveis e constantes de função
Variáveis e constantes definidas dentro de uma função são visíveis (ou seja, podem ser usadas) apenas dentro dessa função:
function print() {
var x = 5;
let y = 8;
const z = 9;
console.log("Function print: x =", x);
console.log("Function print: y =", y);
console.log("Function print: z =", z);
}
print();
console.log("Global: x =", x); // Uncaught ReferenceError: x is not defined
As variáveis x
y
z
Function print: x = 5
Function print: y = 8
Function print: z = 9
Uncaught ReferenceError: x is not defined
Aqui vemos que ao tentar acessar a variável x
print()
var
let
const
Variáveis locais em blocos de código, condições e laços
Com variáveis definidas em blocos de código anônimos, bem como em laços e construções condicionais, a situação é um pouco mais complicada.
Variável var
Uma variável declarada com var
// bloco anônimo
{
var a = 5;
}
console.log("a =", a); // a = 5
// construção condicional
if(true) {
var b = 6;
}
console.log("b =", b); // b = 6
// laço
for(let i = 0; i < 5; i++) {
var c = 7;
}
console.log("c =", c); // c = 7
A única condição é que o bloco de código deve ser executado para inicializar a variável. Assim, no exemplo acima, a condição na construção if
for
if(false) {
var b = 6;
}
console.log("b =", b); // b = undefined
// laço
for(let i = 1; i < 0; i++) {
var c = 7;
}
console.log("c =", c); // c = undefined
Neste caso, ainda podemos acessar as variáveis, mas elas terão o valor undefined
Variável let e Constantes
Agora vejamos como se comportam as variáveis declaradas com a palavra-chave let
{
let a = 5;
}
console.log("a =", a); // Uncaught ReferenceError: a is not defined
Neste caso, receberemos um erro. Só podemos usar variáveis let
O mesmo se aplica às constantes:
{
const b = 5;
}
console.log("b =", b); // Uncaught ReferenceError: b is not defined
Escopo de variáveis
E se tivermos duas variáveis - uma global e outra local - com o mesmo nome?
var z = 89;
function print() {
var z = 10;
console.log(z); // 10
}
print(); // 10
Neste caso, a função usará a variável z
Ocultando a Variável var
Foi mencionado anteriormente que var
function displayZ() {
var z = 20;
{
var z = 30; // Não define uma nova variável, mas altera o valor da variável z no nível da função
console.log("Bloco:", z);
}
console.log("Função:", z);
}
displayZ();
Aqui, a declaração da variável z
Bloco: 30 Função: 30
Ocultando a Variável let
Como mencionado anteriormente, a palavra-chave let
var
let z = 10;
function displayZ() {
let z = 20;
{
let z = 30;
console.log("Block:", z);
}
console.log("Function:", z);
}
displayZ();
console.log("Global:", z);
Aqui, dentro da função displayZ
z
z
E neste caso, obtemos a seguinte saída do console:
Bloco: 30 Função: 20 Global: 10
Constantes
Tudo o que foi dito sobre a palavra-chave let
const
const z = 10;
function displayZ() {
const z = 20;
{
const z = 30;
console.log("Block:", z); // 30
}
console.log("Function:", z); // 20
}
displayZ();
console.log("Global:", z); // 10
Cadeia de Escopo / Scope Chain
Ao executar o código, quando o interpretador encontra algum identificador (nome de uma variável, constante ou função), ele inicialmente procura a definição desse identificador no escopo atual. Isso permite o funcionamento correto do escopo de variáveis e constantes. Por exemplo:
const z = 10;
function displayZ() {
const z = 20;
console.log(z); // 20
}
displayZ(); // 20
Aqui, o interpretador vê que dentro da função displayZ
z
const z = 20
Outro exemplo:
const z = 10;
function displayZ() {
console.log(z); // 10
}
displayZ(); // 10
Como a função displayZ
z
Variáveis não Declaradas
Em JavaScript, é possível declarar variáveis sem usar as palavras-chave let
var
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Programício</title>
</head>
<body>
<script>
{
username = "Tom";
}
console.log(username); // não há erro
{
console.log(username); // não há erro, está disponível dentro de outros blocos de código
}
</script>
</body>
</html>
Se não usarmos as palavras-chave let
var
function setAge() {
userage = 39;
}
setAge();
console.log(userage); // 39
Mesmo que a variável userage não seja definida fora da função setAge
No entanto, se a função não for chamada, a variável não será definida:
function setAge() {
userage = 39;
}
// setAge(); // Função NÃO chamada
console.log(userage); // erro - Uncaught ReferenceError: userage is not defined
Teríamos o mesmo erro se não apenas atribuíssemos um valor à variável, mas também a definíssemos como local em relação à função:
function setAge() {
var userage = 39;
}
setAge();
console.log(userage); // erro - Uncaught ReferenceError: userage is not defined
Strict Mode
Declarar variáveis globais em funções pode levar a erros potenciais. Para evitá-los, usamos o strict mode
Adicionando a expressão
no início do código JavaScript, aplicando o strict mode a todo o código."use strict"
Adicionando a expressão
no início do corpo da função, aplicando o strict mode apenas a essa função."use strict"
Aplicando o strict mode
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Programício</title>
</head>
<body>
<script>
"use strict"; // modo restrito ativado
username = "Tom"; // Uncaught ReferenceError: username is not defined
console.log(username);
</script>
</body>
</html>
Aqui, obtemos um erro SyntaxError: Unexpected identifier
Obtemos um erro semelhante ao declarar uma variável global dentro de uma função:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Programício</title>
</head>
<body>
<script>
"use strict"; // modo restrito ativado
function setAge() {
userage = 39; // Uncaught ReferenceError: userage is not defined
}
setAge();
console.log(userage);
</script>
</body>
</html>
Aplicando o strict mode
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Programício</title>
</head>
<body>
<script>
username = "Tom"; // ok
console.log(username); // Tom
function setAge() {
"use strict"; // modo restrito ativado na função
userage = 39; // Uncaught ReferenceError: userage is not defined
}
setAge();
console.log(userage);
</script>
</body>
</html>