Escopo e fechamento lexical do JavaScript



Tradução do ambiente JavaScript, Lexical Scope and Closures .

Vamos falar sobre o meio ambiente. Nosso enorme planeta é um por todos. Durante a construção de uma nova fábrica de produtos químicos, seria bom isolá-la para que todos os processos internos não deixem suas fronteiras. Podemos dizer que o ambiente e o microclima desta planta são isolados do ambiente externo.

O programa é organizado de forma semelhante. O que você cria externamente - funções externas, instruções condicionais, loops e outros blocos - é um ambiente global externo.



A age constante, a função multiplier e a variável result estão no ambiente externo. Esses componentes têm um escopo global. Um escopo é a área na qual um componente está disponível.

Nesse caso, x é uma constante dentro da função multiplier . Como está dentro de um bloco de código, é uma constante local, não global. É visível apenas dentro da função, mas não fora - seu escopo é local.

A função multiplier possui outro componente do escopo local - este é o argumento num . Defini-lo é mais difícil do que uma constante ou variável, mas se comporta aproximadamente como uma variável local.

Não temos acesso externo a x - parece não existir:



console.log chamado x em um ambiente global no qual não está definido. Como resultado, obtivemos um ReferenceError.

Podemos definir x globalmente:



Temos um x global com um valor conhecido, mas o x local na função multiplier ainda é visível apenas por dentro. Esses x não estão conectados de forma alguma - eles estão em ambientes diferentes. Apesar do mesmo nome, eles não se misturam.

Qualquer bloco de código entre chaves se torna um ambiente local. Aqui está um exemplo de uso if :



O mesmo acontece com while e for loops.

Então local significa invisível do lado de fora. Ou seja, global é visível em todos os lugares, mesmo dentro de objetos? Sim



A variável global a mudou dentro da função changer . A função entra em vigor somente quando chamada, não quando definida; portanto, inicialmente a=0 e, quando chamada, o changer assume o valor 1 .

É fácil sucumbir à tentação e colocar tudo em um escopo global, esquecendo todas as complexidades dos ambientes individuais - mas essa é uma péssima idéia. Variáveis ​​globais tornam seu código extremamente frágil, qualquer elemento pode quebrar qualquer outro a qualquer momento. Portanto, não use o escopo global e mantenha tudo no lugar.

Parte II Âmbito lexical


Dê uma olhada neste programa:



A função multiplier retorna os resultados da multiplicação a e b . a dado internamente, mas b não b .

Ao tentar executar a operação de multiplicação a*b , o JavaScript procura os valores de a e b . Ele começa a procurar dentro e depois sai, estudando uma área após a outra, até encontrar o que estava procurando ou não entender que é impossível encontrar.

Portanto, neste exemplo, o JavaScript começa a procurar dentro da área local - dentro da função multiplier . Ele imediatamente encontra o valor e vai para b . b ele não encontra no ambiente local, então vai além. Lá ele aprende que b é 10 . Então a*b transforma em 5*10 e depois em 50 .

Esse pedaço de código pode estar dentro de outra função, que também está dentro de outra função. Sem encontrar b na primeira camada, o JavaScript continuaria pesquisando tudo em novas e novas camadas, cada vez mais.

Observe que a=7 não afeta o resultado dos cálculos de forma alguma: o valor de a foi encontrado dentro, portanto, o externo a não desempenha a papel.

Isso é chamado de escopo lexical. O escopo de qualquer componente é determinado pela localização desse componente no código, e os blocos aninhados têm acesso a áreas externas.

Parte III Curto-circuito


Ambientes e escopos são suportados pela maioria das linguagens de programação, e esse mecanismo permite a introdução de fechamentos. O fechamento é inerentemente uma função que "lembra" entidades externas usadas internamente.

Antes de continuar, vamos relembrar como as funções são criadas e usadas:



f é uma função bastante inútil que sempre retorna 0 . O conjunto consiste em duas partes - uma constante e a própria função.

É importante lembrar que esses são componentes separados. O primeiro componente é uma constante chamada f . Seu valor pode ser um número ou um valor de sequência. Nesse caso, o valor é uma função.

Nas lições anteriores, citamos uma analogia: as constantes são como folhas de papel com um nome de um lado e um valor do outro. Assim, f é um pedaço de papel com f escrito de um lado e uma descrição da função sendo lançada do outro.

Ao chamar esta função:



Uma nova "caixa" é criada com base na descrição de uma folha de papel.

De volta aos fechamentos. Aqui está um código de exemplo.



A função createPrinter cria uma constante de name e, em seguida, uma função chamada printName . Ambos são locais para a função createPrinter e estão disponíveis apenas dentro dela.

printName próprio printName não possui componentes locais, mas há acesso ao escopo em que é criado e ao ambiente externo, onde é atribuído um name à constante.

A função createPrinter retorna a função printName . Lembre-se de que as definições de função são descrições de funções em execução, são apenas elementos de dados, como números ou cadeias. Portanto, podemos retornar a definição de uma função da mesma maneira que retornamos números.

No escopo externo, criamos a constante myPrinter e configuramos o valor de retorno como createPrinter . Como uma função é retornada, o myPrinter também se torna uma função. Quando você chama, King aparece na tela.

O engraçado é que a constante name foi criada dentro da função createPrinter . A função foi chamada e executada. Como você sabe, quando uma função termina de funcionar, ela deixa de existir. A caixa mágica desaparece junto com todo o conteúdo.

Mas ele retornou outra função que de alguma forma lembrava o name constante. Assim, ao chamar myPrinter obtivemos King - o valor que a função lembra, apesar de essa área não existir mais.

A função que createPrinter retorna é chamada de fechamento. Um fechamento é uma combinação de uma função e o ambiente em que foi definido. A função "incluía" em si certas informações recebidas no escopo.

Isso pode parecer uma peculiaridade estranha do JavaScript, mas o uso inteligente de fechamentos pode ajudar a tornar seu código mais agradável, limpo e legível. O princípio de retornar funções, como retornar números e valores de string, oferece mais liberdade de manobra.

Source: https://habr.com/ru/post/pt460861/


All Articles