Escopo Lexical em JavaScript – O que exatamente é escopo em JS?
Tags: javascript, programming, tutorial
Published: 2022-12-30 18:28:42

O termo "escopo lexical" pode parecer difícil de entender á primeira vista. Mas é útil entender o que cada palavra signicia. Portanto, este artigo explicará o escopo lexical examinando primeiro o significa de "escopo" e "lexical". 

Então vamos começar a entender o termo "escopo".

## O que é exatamente o Escopo?

Escopo refere-se a área onde um item (como uma função ou variável) é visível e acessível a outro código.

Observação:

- Escopo significa área, espaço ou região.
- Escopo global significa espaço global ou um espaço público.
- Escopo local significa uma região local ou uma região restrita.

Aqui está um exemplo:

```jsx
// Define uma variável em um escopo global:
const fullName = "Oluwatobi Sofela";

// Definir funções aninhadas:
function profile() {
  function sayName() {
    function writeName() {
      return fullName;
    }
    return writeName();
  }
  return sayName();
}
```
No trecho acima, definimos a variável `fullName` no escopo global. Isso significa que é visível e acessível globalmente para todo o código dentro do script.

Mas definimos `writeName()` dentro da função `sayName()`, então ela tem escopo local para `sayName()`.

Em outras palavras, `writeName()` é localmente visível e acessível apenas para codificar na função `sayName()`.

Tenha em mente que sempre que a função `writeName()` for invocada, o computador não irá direto para o escopo global para chamar a variável `fullName`. Em vez disso, ele deve passar sequencialmente pela **<u>cadeia de escopo</u>** para procurar arquivos `fullName`.

## O que é uma cadeia de escopo?

Uma cadeia de escopo refere-se aos espaços exclusivos que existem do escopo onde uma variável foi chamada para o escopo global.

Aqui está um exemplo:

```jsx
// Define uma variável em um escopo global:
const fullName = "Oluwatobi Sofela";

// Definir funções aninhadas:
function profile() {
  function sayName() {
    function writeName() {
      return fullName;
    }
    return writeName();
  }
  return sayName();
}
```

No trecho acima, observe que a variável `fullName` foi chamada do escopo da função `writeName()`.

Portanto, a cadeia de escopo que existe desde a chamada da variável até o escopo global é:

`writeName() scope ---> sayName() scope ---> profile() scope ---> global scope`

Em outras palavras, há quatro espaços do escopo de invocação do `fullName`, até seu escopo lexical (o escopo global neste caso).

## Como funciona a cadeia de escopo?

A cadeia de escopo do JavaScript determina a hierarquia de lugares pelos quais o computador deve passar — ​​um após o outro — para encontrar o escopo léxico (origem) da variável específica que foi chamada.

Por exemplo, considere o código abaixo:

```jsx
// Define uma variável em um escopo global:
const fullName = "Oluwatobi Sofela";

// Definir funções aninhadas:
function profile() {
  function sayName() {
    function writeName() {
      return fullName;
    }
    return writeName();
  }
  return sayName();
}
```

No trecho acima, sempre que a função `profile()` for invocada, o computador primeiro invocará a função `sayName()` (que é o único código na função `profile()`).

Em segundo lugar, o computador invocará a função `writeName()` (que é o único código na função `sayName()`).

Nesse ponto, como o código em `writeName()` instrui o computador a chamar e retornar o conteúdo da variável `fullName`, o computador chamará fullName. Mas não irá diretamente para o escopo global chamar fullName.

Em vez disso, o computador deve percorrer passo a passo a cadeia de escopo para procurar o escopo léxico de `fullName`.

Então, aqui estão as etapas sequenciais que o computador deve executar para localizar  o escopo léxico de `fullName`:

1. Primeiramente, o computador verificará se foi `fullName` definido localmente dentro da função `writeName()`. Mas não encontrará nenhuma definição de `fullName` lá, então ele se move para o próximo escopo para continuar sua busca.

2. Em segundo lugar, o computador procurará a definição de `fullName`  em `sayName()`(o próximo espaço na cadeia de escopo). Ainda assim, ele não o encontra lá, então sobe a escada para o próximo escopo.

3. Em terceiro lugar, o computador procurará a definição de `fullName` na função `profile()`. Ainda assim, `fullName` não é encontrado lá. Assim, o computador avança para buscar o escopo lexical de `fullName` na próxima região da cadeia de escopo.

4. Em quarto lugar, o computador vai para o escopo global (o seguinte escopo após `profile()`). Felizmente, ele encontra a definição de `fullName` lá! Portanto, ele pega seu conteúdo ( "Oluwatobi Sofela") e o devolve.

## Hora de praticar com escopo 🤸‍♂️🏋️‍♀️🏊‍♀️

Considere o script abaixo. Qual das três variáveis fullName ​​o computador chamará?

```jsx
// First fullName variable defined in the global scope:
const fullName = "Oluwatobi Sofela";

// Nested functions containing two more fullName variables:
function profile() {
  const fullName = "Tobi Sho";
  function sayName() {
    const fullName = "Oluwa Sofe";
    function writeName() {
      return fullName;
    }
    return writeName();
  }
  return sayName();
}
```
O computador chamará a primeira, segunda ou terceira variável fullName?

**Observação:** você se beneficiará muito mais com este tutorial se tentar fazer o exercício sozinho.

Se você ficar preso, não desanime. Em vez disso, revise a lição e tente novamente.

Depois de dar o seu melhor (você só vai se enganar se não o fizer!), Vá em frente para ver a resposta correta abaixo.

### Você acertou?

Das três definições fullName  presentes no script acima, o computador irá chamar e retornar aquela definida na função `sayName()`.

A variável `fullName` de `sayName()` será chamada porque `sayName()` é o escopo dentro do qual o computador encontrará pela primeira vez uma definição fullName.

Portanto, quando `profile()` for invocado, o valor retornado será "Oluwa Sofe".

### Algumas coisas a ter em mente:

- Suponha que o computador não tenha encontrado  a definição de `fullName` em nenhum dos escopos. Nesse caso, o computador retornará Uncaught ReferenceError: fullName is not defined.

- O escopo global é sempre o último escopo de qualquer cadeia de escopo JavaScript. Em outras palavras, o escopo global é onde todas as pesquisas terminarão.

- Um escopo interno (filho) tem acesso a seu escopo pai (externo), mas um escopo externo não tem acesso a seu escopo filho.
Por exemplo, no snippet acima, `writeName()` pode acessar códigos dentro de qualquer escopo pai (`sayName()`, `profile()` ou o escopo global).
No entanto, nem `sayName()`, `profile()` nem o escopo global podem acessar nenhum dos códigos de `writeName()`.

## Revisão rápida do escopo até agora

O escopo do JavaScript tem tudo a ver com espaço.

Então, da próxima vez que seu parceiro chamar você para seu espaço privado, lembre-se de que ele está convidando você para seu espaço privado 😜!

Quando você chegar lá, pergunte a eles sobre o melhor jogo lexical deles...

Mas o que significa léxico, ouvi você perguntar? Vamos descobrir abaixo.

## O que significa Lexical?

Lexical refere-se à definição das coisas.

Qualquer coisa relacionada à criação de palavras, expressões ou variáveis ​​é denominada lexical.

Por exemplo, um jogo de scrabble é uma atividade lexical porque se relaciona com a criação de palavras.

Além disso, alguém cujo trabalho esteja relacionado à lingüística (o estudo das línguas) tem uma carreira lexical.

Nota: Outro nome para um dicionário é léxico. Em outras palavras, um léxico é um dicionário onde as palavras são listadas e definidas.

Agora que sabemos o que significa escopo e léxico, podemos falar sobre escopo lexical.

## O que é escopo léxico em JavaScript?

Escopo léxico é a área de definição de uma expressão.

Em outras palavras, o escopo léxico de um item é o local em que o item foi criado.

**Observação:**

Outro nome para escopo léxico, é escopo estático.
O local em que um item foi invocado (ou chamado) não é necessariamente o escopo lexical do item. Em vez disso, o espaço de definição de um item é seu escopo léxico.

## Exemplo de Escopo Lexical

Considere o código abaixo:

```jsx
// Define a variable in the global scope:
const myName = "Oluwatobi";

// Call myName variable from a function:
function getName() {
  return myName;
}
```

No trecho acima, observe que definimos a variável `myName` no escopo global e a chamamos na função `getName()`.

**Pergunta:** Qual dos dois espaços é o escopo lexical de `myName`? É o escopo global ou o escopo local da função `getName()`?

Resposta: Lembre-se de que escopo léxico significa espaço de definição — não espaço de invocação. Portanto, o escopo lexical de `myName` é o escopo global porque definimos `myName` no ambiente global.

### Outro exemplo de escopo lexical

```jsx
function getName() {
  const myName = "Oluwatobi";
  return myName;
}
```

Pergunta: Onde está o escopo lexical de `myName`?

Resposta: Observe que criamos e chamamos `nyName` dentro de `getName()`. Portanto, o escopo léxico de `myName` é o ambiente local de `getName()`, porque `getName()` é o espaço de definição de `myName`.

## Como funciona o escopo lexical?

O ambiente de definição de uma expressão JavaScript determina o código permitido para acessá-la.

Em outras palavras, apenas o código dentro do escopo léxico de um item pode acessá-lo.

Por exemplo, considere o código abaixo:

```jsx
// Define a function:
function showLastName() {
  const lastName = "Sofela";
  return lastName;
}

// Define another function:
function displayFullName() {
  const fullName = "Oluwatobi " + lastName;
  return fullName;
}

// Invoke displayFullName():
console.log(displayFullName());

// The invocation above will return:
Uncaught ReferenceError: lastName is not defined
```
Observe que a invocação de `displayFullName()` no snippet acima retornou um `ReferenceError não capturado`. O erro retornou porque apenas o código dentro do escopo léxico de um item pode acessar o item.

Portanto, nem a função `displayFullName()` nem seu código interno podem acessar a variável `lastName`, porque `lastName` foi definido em um escopo diferente.

Em outras palavras, o escopo léxico de `lastName` é diferente daquele de `displayFullName()`.

O espaço de definição de lastName é `showLastName()` enquanto o escopo léxico de `displayFullName()` é o ambiente global.

Agora, considere este outro código abaixo:

```jsx
function showLastName() {
  const lastName = "Sofela";
  return lastName;
}

// Define another function:
function displayFullName() {
  const fullName = "Oluwatobi " + showLastName();
  return fullName;
}

// Invoke displayFullName():
console.log(displayFullName());

// The invocation above will return:
"Oluwatobi Sofela"
```

O snippet acima, `displayFullName()` retornou com sucesso "Oluwatobi Sofela" porque `displayFullName()` e `showLastName()` estão no mesmo escopo léxico.

Em outras palavras, `displayFullName()` poderia invocar `showLastName()`, porque as duas funções são definidas no escopo global.

**Observação:**

- No exemplo 2 acima, `displayFullName()` não obteve acesso à variável `lastName` de `showLastName()`. Em vez disso, `displayFullName()` invocou `showLastName()` — que então retornou o conteúdo de sua variável `lastName`.

- Uma alternativa ao escopo léxico, é o escopo dinâmico — mas raramente é usado na programação. Apenas algumas linguagens, como bash, usam escopo dinâmico.

## Conclusão

Sempre que você ouvir lexical, pense na definição.

Assim, o escopo lexical de um carro, variável, telefone, função ou maiô refere-se à sua região de definição. 

Este artigo discutiu o que significa escopo léxico em JavaScript. Também vimos por que é um importante conceito de programação.

Obrigado por ler!