Uma introdução ao escopo em JavaScript

O escopo define a vida útil e a visibilidade de uma variável. As variáveis ​​não são visíveis fora do escopo em que foram declaradas.

JavaScript tem escopo de módulo, escopo de função, escopo de bloco, escopo léxico e escopo global.

Âmbito global

Variáveis ​​definidas fora de qualquer função, bloco ou escopo de módulo têm escopo global. Variáveis ​​em escopo global podem ser acessadas de qualquer lugar no aplicativo.

Quando um sistema de módulo está habilitado, é mais difícil criar variáveis ​​globais, mas ainda é possível fazer isso. Ao definir uma variável em HTML, fora de qualquer função, uma variável global pode ser criada:

 let GLOBAL_DATA = { value : 1};  console.log(GLOBAL_DATA);

Quando não há um sistema de módulo instalado, é muito mais fácil criar variáveis ​​globais. Uma variável declarada fora de qualquer função, em qualquer arquivo, é uma variável global.

Variáveis ​​globais estão disponíveis durante o tempo de vida do aplicativo.

Outra maneira de criar uma variável global é usar o windowobjeto global em qualquer lugar do aplicativo:

window.GLOBAL_DATA = { value: 1 };

Neste ponto, a GLOBAL_DATAvariável está visível em todos os lugares.

console.log(GLOBAL_DATA)

Como você pode imaginar, essas práticas são práticas ruins.

Escopo do módulo

Antes dos módulos, uma variável declarada fora de qualquer função era uma variável global. Nos módulos, uma variável declarada fora de qualquer função fica oculta e não disponível para outros módulos, a menos que seja explicitamente exportada.

A exportação disponibiliza uma função ou objeto para outros módulos. No próximo exemplo, exporto uma função do sequence.jsarquivo de módulo:

// in sequence.js export { sequence, toList, take };

A importação disponibiliza uma função ou objeto de outros módulos para o módulo atual.

import { sequence, toList, toList } from "./sequence";

De certa forma, podemos imaginar um módulo como uma função autoexecutável que recebe os dados de importação como entradas e retorna os dados de exportação.

Escopo da Função

O escopo da função significa que os parâmetros e variáveis ​​definidos em uma função são visíveis em qualquer lugar dentro da função, mas não são visíveis fora da função.

Considere a próxima função que é executada automaticamente, chamada IIFE.

(function autoexecute() { let x = 1; })(); console.log(x); //Uncaught ReferenceError: x is not defined

IIFE significa Immediately Invoked Function Expression e é uma função executada imediatamente após sua definição.

Variáveis ​​declaradas com vartêm apenas escopo de função. Ainda mais, as variáveis ​​declaradas com varsão içadas para o topo de seu escopo. Dessa forma, eles podem ser acessados ​​antes de serem declarados. Dê uma olhada no código abaixo:

function doSomething(){ console.log(x); var x = 1; } doSomething(); //undefined

Isso não acontece para let. Uma variável declarada com só letpode ser acessada após sua definição.

function doSomething(){ console.log(x); let x = 1; } doSomething(); //Uncaught ReferenceError: x is not defined

Uma variável declarada com varpode ser declarada novamente várias vezes no mesmo escopo. O código a seguir é adequado:

function doSomething(){ var x = 1 var x = 2; console.log(x); } doSomething();

Variáveis ​​declaradas com letou constnão podem ser declaradas novamente no mesmo escopo:

function doSomething(){ let x = 1 let x = 2; } //Uncaught SyntaxError: Identifier 'x' has already been declared

Talvez nem tenhamos que nos preocupar com isso, pois varjá começou a ficar obsoleto.

Escopo do Bloco

O escopo do bloco é definido com chaves. Ele é separado por {e }.

Variáveis ​​declaradas com lete constpodem ter escopo de bloco. Eles só podem ser acessados ​​no bloco em que estão definidos.

Considere o próximo código que enfatiza o letescopo do bloco:

let x = 1; { let x = 2; } console.log(x); //1

Em contraste, a vardeclaração não tem escopo de bloco:

var x = 1; { var x = 2; } console.log(x); //2

Outro problema comum em não ter escopo de bloco é o uso de uma operação assíncrona como setTimeout()em um loop. O código de loop de fluxo exibe o número 5, cinco vezes.

(function run(){ for(var i=0; i<5; i++){ setTimeout(function logValue(){ console.log(i); //5 }, 100); } })();

A forinstrução de loop, com a letdeclaração, cria uma nova variável local para o escopo do bloco, para cada iteração. O próximo código de loop é mostrado 0 1 2 3 4 5.

(function run(){ for(let i=0; i<5; i++){ setTimeout(function log(){ console.log(i); //0 1 2 3 4 }, 100); } })();

Âmbito Lexical

O escopo lexical é a capacidade da função interna de acessar o escopo externo no qual está definida.

Considere o próximo código:

(function autorun(){ let x = 1; function log(){ console.log(x); }; function run(fn){ let x = 100; fn(); } run(log);//1 })();

A logfunção é um fechamento. Ele se refere à xvariável de sua função pai autorun(), não à da run()função.

A função de fechamento tem acesso ao escopo em que foi criada, não ao escopo em que foi executada.

The local function scope of autorun() is the lexical scope of the log() function.

Scope chain

Every scope has a link to the parent scope. When a variable is used, JavaScript looks down the scope chain until it either finds the requested variable or until it reaches the global scope, which is the end of the scope chain.

Look at the next example:

let x0 = 0; (function autorun1(){ let x1 = 1; (function autorun2(){ let x2 = 2; (function autorun3(){ let x3 = 3; console.log(x0 + " " + x1 + " " + x2 + " " + x3);//0 1 2 3 })(); })(); })();

The autorun3() inner function has access to the local x3 variable. It has also access to the x1 and x2 variables from the outer functions and the x0 global variable.

If it cannot find the variable, it will return an error in strict mode.

"use strict"; x = 1; console.log(x) //Uncaught ReferenceError: x is not defined

In non-strict mode, referred to as “sloppy mode”, it will do a bad thing and create a global variable.

x = 1; console.log(x); //1

Conclusion

Variables defined in global scope are available everywhere in the application.

Em um módulo, uma variável declarada fora de qualquer função fica oculta e não está disponível para outros módulos, a menos que seja explicitamente exportada.

O escopo da função significa que os parâmetros e variáveis ​​definidos em uma função são visíveis em qualquer lugar dentro da função

Variáveis ​​declaradas com lete consttêm escopo de bloco. varnão tem escopo de bloco.

O Discover Functional JavaScript foi nomeado um dosmelhores novos livros de Programação Funcional por BookAuthority !

Para mais informações sobre a aplicação de técnicas de programação funcional no React, dê uma olhada em Functional React .

Aprenda o React funcional , de forma baseada em projetos, com a Arquitetura Funcional com React e Redux .

Siga no Twitter