Instituto Federal de Mato Grosso do SulNovembro/2021

IFMS marca

07. Escopo de Identificadores

Algoritmos 2

Prof. Rodrigo Duran

Nesta aula vamos:


  • Vamos entender os diversos tipos de escopo de identificadores em JavaScript

    Existem diversas formas de se declarar uma variável em JavaScript. Vamos aprender a identificar e diferenciar cada uma dessas formas e usar corretamente o escopo de variáveis de cada tipo.

Escopo de Variáveis

O escopo de variáveis nos diz basicamente onde e como as variáveis são válidas (acessíveis) dentro de um programa.
Um aviso: seguindo boas práticas de programação você pode evitar a maioria dos problemas relacionados a escopo!
Discutiremos mais a fundo essas questões mais adiante...
Escopo

O que é escopo?


É a parte do programa em que um identificador (de variáveis) pode ser legalmente usado para acessar um componente de um programa.

O escopo determina dois aspectos fundamentais de componentes de um programa:

  • Visibilidade: Diz respeito à possibilidade de acesso a uma variável dentro de partes diferentes de um programa.

  • Atualização: Determina se uma variável pode ser redeclarada ou atualizada.

Principios básicos

Escopo: Principios básicos


Dois fatores são importantes na definição de escopo de um identificador em JavaScript:

  1. Como um identificador foi declarado.
  2. Onde o identificador foi declarado

Identificadores podem ser declarados de várias formas, dentre eles:

  • usando var, let e const;
  • Parâmetros de funções;
  • Declaração de funções.

Alguns dos locais onde um identificador pode ser declarado:

  • Contexto global;
  • Corpo de uma função;
  • Um bloco comum;
  • Dentro de uma estrutura de controle (e.g., loop)

Tipos de declaração: Var


Identificadores declarados utilizando o var tem escopo de função ou global. Quando declarados dentro de funções usando o var, variáveis tem escopo de função: seu valor só é acessado dentro da função onde a variável foi declarada. Fora de funções ela tem escopo global.

var a = 20;
A variável a tem escopo global
function algumacoisa(){
  console.log(a)
  var x = 1
A variável x tem escopo de função
}

console.log(x)

20
Erro! x não foi definido!

Variáveis do tipo var podem ser redeclaradas e redefinidas

var s = "Olá Info 2!"
var s = "Redeclarei a variável s..."
console.log(s)

Redeclarei a variável s...

var s = "Olá Info 2!"
s = "Redefini s..."
console.log(s)

Redefini s...

Problemas com o var

A maior parte dos problemas com o var acontecem ao acessar a variável fora de seu escopo original. Por exemplo, ao usar o var para declarar uma variável de controle em um loop ...

for(var x = 0; x < 5; ++x) {
  console.log(x)
0 , 1 , 2 , 3 , 4
}
console.log(x)
5
O calor de x continua válido após o escopo do bloco do loop

Tipos de declaração: let


Identificadores declarados utilizando o let tem escopo de bloco ou global. Quando declarados dentro de blocos usando o let, variáveis tem escopo de bloco: seu valor só é acessado dentro do bloco onde a variável foi declarada. Fora do bloco ela tem escopo global.

Escoplo let

Variáveis do tipo let podem ser redefinidas mas não redeclaradas!

let s = "Olá Info 2!"
let s = "Redeclarei a variável s..."
console.log(s)

O identificador s já foi declarado

let s = "Olá Info 2!"
s = "Redefini s..."
console.log(s)

Redefini s...

let previne o reuso indevido de variáveis...


for(let x = 0; x < 5; ++x) {
  console.log(x)
0 , 1 , 2 , 3 , 4
}
console.log(x)
Identificador x não definido!

Via de regra: use o let!

Tipos de declaração: const


Identificadores declarados utilizando o const tem escopo de bloco ou global. Quando declarados dentro de blocos usando o const, variáveis tem escopo de bloco: seu valor só é acessado dentro do bloco onde a variável foi declarada. Fora do bloco ela tem escopo global.

Escoplo let

Variáveis do tipo const não podem ser redefinidas nem redeclaradas.

const s = "Olá Info 2!"
const s = "Redeclarei a variável s..."
console.log(s)

O identificador s já foi declarado

const s = "Olá Info 2!"
s = "Redefini s..."
console.log(s)

Atribuição a uma variável constante.

Todas as variáveis do tipo const devem ser inicializadas na declaração

Via de regra: use o const ao declarar valores imutáveis, mas que serão reutilizados no decorrer do código.

Exemplos: chaves de acesso, constantes matemáticas, strings de saída, etc.

Parâmetros e variáveis locais


Parâmetros de função tem escopos de função. Todas as variáveis locais, declaradas dentro do bloco da função terão bloco de função se declaradas com var ou de bloco se declaradas com let ou const. Note que como a própria função também é um bloco, no caso abaixo os 2 escopos se sobrepõem.

Escoplo local

Em relação à redefinição e redeclaração, as variáveis locais seguem a regra dos seus tipos de declaração (const, var ou let)

Parâmetros de função podem ser redefinidos mas não redeclarados.

const minhafuncao = function (parametro){
  console.log(parametro)
  parametro = 30
  let parametro = 20
}

minhafuncao(2)

O identificador parametro já foi declarado

Coisas que você nunca deveria fazer

No seu código :)

Mas algumas pessoas vão fazer mesmo assim :(

Comer manga com leita não faz mal, é apenas uma brincadeira com essa lenda urbana

Regras básicas de bos práticas em programação







Que muito provavelmente farão com que você nunca se preocupe com escopo das variáveis...

1. Não usar variáveis globais (além do estritamente necessário -- quase nunca)

O que acontece quando temos conflitos de escopo de variáveis?

var var1 = 20

const minhafuncao = function (parametro){
  var var1 = 30
  console.log(var1)
}

minhafuncao(10)
console.log(var1)

30, 20

A variável var1 declarada na primeira linha do programa tem escopo global. Entretanto, ela foi redeclarada em um outro escopo de função. O escopo mais interno, ou seja o que está sendo executado no momento, tem precedência sobre o escopo externo (global).

Efetivamente, as variáveis var1 (global) e var1(local) são entes diferentes (dentro da função minhafuncao)

2. Organizar a declaração de variáveis -- cuidado ao declarar variáveis!

var hello = "say Hi"
let times = 4

if (times > 3) {
  var hello = "say Hello instead"
  console.log(hello)
say Hello instead
}
console.log(hello)
say hello instead

A variável hello foi redeclarada dentro do escopo de bloco. Como ela foi declarada como var, ela continua com o valor atualizado fora do bloco.

Veja que o mesmo não acontece utilizando o let

let hello = "say Hi"
let times = 4
if (times > 3) {
  let hello = "say Hello instead"
  console.log(hello)
say Hello instead
}
console.log(hello)
say Hi

A variável hello foi redeclarada dentro do escopo de bloco. Como as variáveis estão em escopos diferentes, mesmo usando o let isso não viola as condições de escopo em JavaScript. Mas veja que o resultado é diferente dentro e fora do escopo de bloco.

Mais boas práticas...


Não "reutilize" variáveis no seu programa. Cada variável tem um objetivo. Objetivos diferentes, variáveis diferentes.

Programas são feitos para serem lidos por humanos. Nomeie variáveis de acordo com seu objetivo no código.

Linguagens tem "guias de estilo" (Style Guides) que apresentam várias dessas boas práticas:

Evite mutações: alterar o valor de um parâmetro dentro de uma função que reflete no seu valor fora da função. E.g., alterar o parâmetro array no map do projeto de filtros.