O único jeito de criar escopo em JavaScript é definindo uma função, basicamente, sempre que uma função é definida ela cria um novo escopo, esse escopo tem uma ligação com o escopo de onde a função foi definida (confusing?) e isso é o que conhecemos como Scope Chain, ou cadeia de escopo.
Por definição toda função em JavaScript é um closure, pois são objetos, e tem uma cadeia de escopo associada a elas.
Agora, um pouco de prática pra clarear a mente:
var scope = 'global';
function fnOuter () {
console.log(scope); // > undefined
var scope = 'outer';
return function () {
console.log(scope); // > outer
scope = 'inner';
return scope;
}();
}
console.log(scope); // > global;
console.log(fnOuter()); // > 'inner';
console.log(scope); // > global;
Notou algo bem loco por aí?
O console.log(scope);
no começo da
fnOuter()
retorna
undefined
isso é devido as declarações no
JavaScript serem todas hoisted (tem um post aqui com mais
info), então quando definimos uma nova
var
nossa variable é 'hoisted' no
topo da função e inicializado com
undefined
. Cool, huh?
Outro detalhe interessante é que como declaramos uma nova variável, a
mudança do scope = 'inner'
tem efeito
apenas na variável da função fnOuter()
e
não mudamos o scope global, usar o mesmo nome de uma função paí ou global
não é recomendado (não faça isso em seus projetos!) e é
conhecido como variable shadowing.
Usamos aqui apenas para exemplificar a idéia de escopo.