JavaScript Encerramento vs.Local
-
21-12-2019 - |
Pergunta
Eu tenho um Javascript arquivo principal que é delimitada por um imediatamente chamada de fechamento (para não poluir 'global':
(function () {
"use strict";
var closureVariable = [];
...
}());
Eu fiz um simples osso pontas de codificação de erro ao remover uma variável de um cabeçalho de função tal que meu código teve uma vírgula em vez de um ponto-e-vírgula:
function fred () {
var i,
closureVariable = [1,2,3,4];
confused();
}
function confused () {
console.log(closureVariable); // Prints '[]'
}
Certamente, a falta de ponto-e-vírgula no 'var i' de linha era o problema.No entanto, o comportamento eu pensei que deve acontecer é que o meu agora definidos localmente variável 'closureVariable" deveria ter sombreado de alto nível para a definição do escopo, e o valor do meu definidos localmente variável deve ter sido disponível para funções mais para baixo no âmbito da cadeia (isto é, a função 'confuso' deve ter impresso '[1,2,3,4]';
O que eu não entendimento sobre o escopo do Javascript cadeias aqui?
Solução
O que você está esperando é conhecido como escopo dinâmico.Este é um idioma válido escolha de design que, apesar de amplamente considerados inferiores de hoje.Não é apenas o que Javascript não.Como muitos idiomas populares, Javascript usa escopo léxico.O que significa confused
âmbito de aplicação não é considerado um escopo filho de fred
's, porque a sua definição não está dentro da definição de fred
.O fato de que fred
chamadas confused
não tem efeito.
Outras dicas
var i,
closureVariable = [1,2,3,4];
faz duas novas variáveis, disponível no fred
função e funções definidas neste âmbito.
Essas variáveis são totalmente diferentes de qualquer variável definida fora da fred
escopo, mesmo se eles tiverem o mesmo nome.
Sombreamento, aqui, significa que a variável nome "closureVariable"
impede qualquer acesso directo para a variável com o mesmo nome, na parte externa do âmbito de aplicação.
Quando você redefiniu o closureVariable por omissão de ponto-e-vírgula foi redefinido apenas no contexto de fred função.O confuso função de existir no contexto de seu encerramento, portanto, ele ainda vê o original closureVariable.Se você teve seu confuso função definida dentro do fred função seria ver o novo closureVariable e gostaria de impressão [1,2,3,4]
(function () {
"use strict";
var closureVariable = [];
function fred () {
var i,
closureVariable = [1,2,3,4];
function confused () {
console.log(closureVariable);
}
confused(); // print [1,2,3,4]
}
})();
Ou se você quiser chamar confuso do lado de fora do fred()
(function () {
"use strict";
var closureVariable = [];
var confused;
function fred () {
var i,
closureVariable = [1,2,3,4];
confused = function () {
console.log(closureVariable);
}
}
confused(); // print [1,2,3,4]
})();