JavaScript: escopo em palavras simples

Bom dia amigos!



O escopo é um conceito importante para determinar a acessibilidade das variáveis. Este conceito está no cerne dos fechamentos, dividindo as variáveis ​​em globais e locais.



Neste artigo, tentarei explicar em termos simples qual é o escopo em JavaScript.



1. Escopo



Antes de mergulhar nos detalhes do escopo, vamos dar uma olhada em um exemplo rápido.



Digamos que definimos uma variável:



const message = 'Hello'
console.log(message) // 'Hello'


Podemos facilmente enviar seu valor para o console. Isso é claro.



Agora vamos colocar a declaração da variável de mensagem no bloco if:



if (true) {
    const message = 'Hello'
}
console.log(message) // ReferenceError: message is not defined


Desta vez, ao tentar acessar a variável, é lançada uma exceção ReferenceError: mensagem não definida.



Por quê isso aconteceu?



Porque o bloco if criou um escopo para a variável de mensagem. E a mensagem só está disponível neste escopo.







Assim, a disponibilidade de variáveis ​​é limitada pelo escopo em que são definidas.



Portanto, o escopo é o escopo das variáveis.



2. Escopo do bloco



Um bloco de código em JavaScript define o escopo das variáveis ​​declaradas com as palavras-chave const e let:



if (true) {
    //    if
    const message = 'Hello'
    console.log(message) // 'Hello'
}
console.log(message) // ReferenceError


O primeiro console.log () imprime com segurança o valor da variável da mensagem no console, uma vez que essa variável é acessada no escopo em que está definida.



No entanto, chamar o segundo console.log () gera um erro porque a variável da mensagem não está disponível em seu escopo externo: a mensagem não existe no contexto atual.



O escopo do bloco também é criado nas instruções if, for, while.



Por exemplo:



for (const color of ['green', 'red', 'blue']) {
    //    for
    const message = 'Hi'
    console.log(color) // 'green', 'red', 'blue'
    console.log(message) // 'Hi', 'Hi', 'Hi'
}
console.log(color) // ReferenceError
console.log(message) // ReferenceError


As variáveis ​​de cor e mensagem existem apenas dentro do bloco for.



O mesmo é verdadeiro para a instrução while:



while (/*  */) {
    //    while
    const message = 'Hi'
    console.log(message) // 'Hi'
}
console.log(message) // ReferenceError


A mensagem definida em while só está disponível neste loop.



Em JavaScript, você pode criar blocos de código autocontidos. Eles também definem seu próprio escopo:



{
    const message = 'Hi'
    console.log(message) // 'Hi'
}
console.log(message) // ReferenceError


2.1. var não tem escopo de bloco



Como vimos nos exemplos anteriores, um bloco de código cria escopo para variáveis ​​declaradas com as palavras-chave const e let. No entanto, isso não funciona para variáveis ​​declaradas com a palavra-chave var.



Vamos considerar um exemplo:



if (true) {
    //    if
    var count = 0
    console.log(count) // 0
}
console.log(count) // 0


A contagem de variável está disponível dentro do bloco if, como esperado. No entanto, também está disponível fora deste bloco!



Isso ocorre porque o bloco de código não cria escopo para variáveis ​​declaradas com a palavra-chave var. Mas a função faz isso.



3. Escopo da função



As funções em JavaScript criam escopo para todas as variáveis, independentemente da palavra-chave com que são declaradas (var, const ou let).



Por exemplo:



function run() {
    //    run()
    var message = ', , !'
    console.log(message)
}
run() // ', , !'
console.log(message) // ReferenceError


A função run () cria um escopo. A mensagem variável está disponível dentro da função, mas não fora.



Da mesma forma, a função cria escopo para variáveis ​​declaradas com const e let, e até mesmo para outras funções e expressões de função:



function run() {
    //    run()
    const two = 2
    let one = 1
    function run2() {}
    var run3 = () => {}

    console.log(two)
    console.log(one)
    console.log(run2)
    console.log(run3)
}
run() // 2 1 ƒ run2() {} () => {}
console.log(two) // ReferenceError
console.log(one) // ReferenceError
console.log(run2) // ReferenceError
console.log(run3) // ReferenceError


4. Visibilidade do módulo



Os módulos ES6 também criam escopo para variáveis, funções e classes.



O módulo de círculo cria um pi constante (para uso interno):



//    circle
const pi = 3.14

console.log(pi) // 3.14

//  pi


A variável pi é declarada dentro do módulo circle e não é exportada de lá.



Em seguida, o módulo de círculo é importado:



import './circle'

console.log(pi) // ReferenceError


A variável pi não está disponível fora do módulo de círculo (até que seja exportada usando export).



O escopo modular encapsula módulos. Isso significa que variáveis ​​privadas (que não são exportadas) são usadas para as próprias necessidades do módulo e são protegidas contra acesso externo.



Assim, podemos dizer que o escopo é um mecanismo de encapsulamento de blocos de código, funções e módulos.



5. Os escopos podem ser aninhados



Um recurso interessante dos escopos é que eles podem ser aninhados uns nos outros.



No exemplo a seguir, a função run () cria um escopo e, dentro dele, um bloco if cria outro escopo:



function run() {
    //    run()
    const message = ', , !'

    if (true) {
        //    if
        const friend = ''
        console.log(message) // ', , !'
    }

    console.log(friend) // ReferenceError
}
run()


O escopo do bloco if está aninhado no escopo da função run ().



Um escopo que está dentro de outro escopo é chamado de escopo interno. No exemplo acima, este é o escopo do bloco if.



Um escopo que contém outro escopo é chamado de escopo externo. No exemplo acima, este é o escopo da função run ().







E quanto à disponibilidade variável? Uma regra simples para lembrar é:



Variáveis ​​do escopo externo estão disponíveis no escopo interno.



Portanto, a variável de mensagem está disponível dentro do bloco if.



6. Escopo global



O escopo global é o escopo mais externo. Ele está disponível para qualquer escopo interno ou local. No navegador, o escopo global é criado quando o arquivo JavaScript especificado no atributo src da tag de script é carregado:



<script src="script.js">




// script.js

// escopo global

let counter = 1



Variáveis ​​declaradas no escopo global são variáveis ​​globais. Eles estão disponíveis em qualquer outra área.



O escopo global é um mecanismo que permite que o tempo de execução do JavaScript (navegador, Node.js) exponha objetos de host (ou seja, de propriedade do ambiente) para aplicativos como variáveis ​​globais.



Por exemplo, janela e documento são variáveis ​​globais (objetos) fornecidos pelo navegador. No Node.js, essa variável é, por exemplo, o objeto do processo.



7. Âmbito lexical



Vamos definir duas funções, uma das quais aninhada na outra:



function outer() {
    //    outer()
    let v = '     outer()!'

    function inner() {
        //    inner()
        console.log(v) // '     outer()!'
    }

    return inner
}

const f = outer()
f()


Dê uma olhada na última linha: inner () é chamado fora do escopo de outer (). Como o JavaScript sabe que o valor impresso no console na função inner () pertence à variável v declarada na função outer ()?



Resposta: graças ao escopo léxico.



JavaScript implementa um mecanismo chamado escopo léxico ou estático. O escopo lexical significa que a acessibilidade das variáveis ​​é determinada estaticamente pela posição dessas variáveis ​​dentro do escopo da função aninhada: as variáveis ​​do escopo da função externa estão disponíveis no escopo da função aninhada.



A definição formal de escopo lexical é a seguinte:



O escopo léxico consiste em escopos externos estaticamente definidos, ou seja, de regiões externas, corrigido pelo uso de variáveis ​​dessas regiões em funções internas.



No exemplo acima, o escopo léxico da função inner () consiste no escopo da função outer ().



Além disso, inner () é um encerramento porque usa o valor da variável do escopo lexical.



8. Isolamento de variáveis



Obviamente, o escopo isola as variáveis. Isso permite que diferentes escopos contenham variáveis ​​com o mesmo nome.



Você pode usar variáveis ​​de contagem, índice, corrente, valor, etc. em diferentes áreas sem a ameaça de colisões (conflitos de nomes).



Por exemplo:



function foo() {
    //    foo()
    let count = 1
    console.log(count) // 1
}

function bar() {
    //    bar()
    let count = 2
    console.log(count) // 2
}

foo()
bar()


Conclusão



O escopo determina a disponibilidade de variáveis. Uma variável declarada no escopo atual está disponível apenas dentro dele.



Em JavaScript, os escopos são criados por blocos, funções e módulos.



As variáveis ​​declaradas com as palavras-chave const e let podem ser em bloco, funcionais ou modulares, enquanto as variáveis ​​declaradas com a palavra-chave var não têm escopo em bloco.



Os escopos podem ser aninhados. Variáveis ​​declaradas no escopo externo estão disponíveis no escopo interno.



O escopo léxico consiste em escopos externos definidos estaticamente. Qualquer função, independentemente de onde seja executada, tem acesso às variáveis ​​de seu escopo lexical (esta é a essência dos encerramentos).



Espero que o artigo tenha sido útil para você. Obrigado pela atenção.



All Articles