Escopo de JavaScript
A escola W3 explicava assim:
Em JavaScript, objetos e funções também são variáveis. O escopo determina a acessibilidade de variáveis, objetos e funções de diferentes partes do código.
Escopo local e escopo global
Em JavaScript, existem dois tipos de escopos - escopo local e escopo global.
A acessibilidade de uma variável é determinada pelo escopo. Se 变量a
for declarada no corpo da função, ela se tornará uma variável local da função e não é acessível de fora.
var global = 321;
function private() {
var a = 123; //局部变量,外部不可见
console.log(a);//123
console.log(global);//321
}
private();
console.log(a); //错误:Uncaught ReferenceError: a is not defined
No código acima, global
é uma variável global, que também pode ser acessada a
no corpo da função , mas é uma variável declarada no corpo da função, e o escopo é limitado ao corpo da função. Quando for chamado externamente, um erro será relatado porque ele é indefinido.
Período de validade de variáveis JavaScript
O período de validade de uma variável JavaScript começa quando ela é criada.
As variáveis locais são excluídas quando a função é concluída.
As variáveis globais serão excluídas quando você fechar a página.
Pré-compilado
Antes de praticar, vamos mencionar a pré-compilação em JS, vamos usá-la mais tarde
1. Criar um objeto AO
é implicitamente criar um objeto vazio AO (Objeto de Ativação).2. Procure o parâmetro formal e as declarações de variável, use o nome do parâmetro formal e o nome da variável como as propriedades do objeto AO e o valor é indefinido.
Observe que esta é uma declaração de variável (var deve ser incluído), mas o nome do parâmetro formal e o nome da declaração da variável não são atribuídos.3. Adicione o formulário às estatísticas do parâmetro real
, ou seja, modifique o valor do atributo denominado parâmetro formal no objeto AO para o parâmetro real passado. Se não houver parâmetro formal, pule esta etapa.4. Encontre a declaração da função. O nome da função é o atributo do objeto AO e o corpo da função é o valor.
Observação: esta é uma declaração de função, não uma função anônima e expressão de função.Resumo: O processo de pré-compilação é o processo de localização de declarações de variáveis, parâmetros formais e declarações de funções. Ele não inicializa e atribui valores, e será inicializado durante a fase de interpretação e execução.
Exercício
Já sabemos os fundamentos do escopo. Vamos testar nosso domínio com algumas perguntas.
Você pode tentar analisá-lo sozinho e, em seguida, analisarei esses tópicos um por um mais tarde.
//题目一:
var a = "aa";
function test() {
console.log(a);
var a = "bb";
console.log(a);
}
test();
alert(a);
//题目二:
(function() {
var a = 5
function a() {
}
console.log(a);
function b() {
}
b = 6;
console.log(b);
var c = d = b
})();
console.log(d);
console.log(c);
//题目三:
var foo = {
n: 1
};
(function(foo) {
console.log(foo.n);
foo.n = 3;
var foo = {
n: 2
}
console.log(foo.n);
})(foo)
console.log(foo.n)
Análise
//题目一:
var a = "aa";
function test() {
console.log(a);
var a = "bb";
console.log(a);
}
test();
alert(a);
Depois que a pré-compilação terminar, execute linha por linha:
Primeiro, a = undefined ——> "aa";
A chamada test()
é executada primeiro console.log(a)
, porque a variável local a é declarada durante a pré-compilação e nenhum valor é atribuído.Neste momento a = undefined
, o resultado da impressão do console é indefinido. (Se não houver var a na função de teste, ela pesquisará durante a execução e encontrará a variável global a para a saída.)
Imediatamente após a variável local a = undefined in test ——> "bb";
Execução console.log(a)
, porque a variável a acaba de receber o valor "bb", o console gera bb
Finalmente, alert(a)
aqui é para distinguir o escopo das variáveis globais e variáveis locais. Obviamente, o resultado da execução aqui irá mostrar o resultado: aa
//题目二:
(function() {
var a = 5
function a() {
}
console.log(a);
function b() {
}
b = 6;
console.log(b);
var c = d = b;
})();
console.log(d);
console.log(c);
Depois que a pré-compilação terminar, execute-a linha por linha:
a = function body ——> 5;
Execute console.log (a), console de impressão 5
b = corpo da função -> 6;
Execute console.log (a), console de impressão 6
Execute c = d = b, ou seja, atribua o valor de c e d igual a 6. (Observação: o d aqui não é declarado com a palavra-chave var e se torna automaticamente um objeto global)
A função de execução imediata é destruída após a execução, mas d é um objeto global, então console.log (d) pode encontrar d e imprimir 6. O escopo de c está na função de execução imediata. Quando a função de execução imediata é executada e destruída, ela não pode ser encontrada globalmente, então o resultado é um erro Uncaught ReferenceError: c is not defined
.
//题目三:
var foo = {
n: 1
};
(function(foo) {
console.log(foo.n);//foo1
foo.n = 3;
var foo = {
n: 2
}
console.log(foo.n);
})(foo)
console.log(foo.n)
Execução console.log(foo.n)
Como a variável local foo declarada no corpo da função não encontra o atributo n, mas o parâmetro real foo passado é encontrado, a saída 1
O que é foo.n = 3
alterado posteriormente é o valor de atributo do atributo n no objeto global foo (porque apenas foo no global tem o atributo n.) 1 torna-se 3
foo = {n:2}
Foo é reatribuído (e declarado novamente na função de execução imediata, o escopo é efetivo na função de execução imediata).
console.log(foo.n)
Produto 2.
A função é executada imediatamente após a destruição, sem o escopo local foo={n: 2}
, a saída é um foo global, desta vez foo = {n: 3}; portanto, a saída 3.
Atributo n. ) 1 torna-se 3
foo = {n:2}
Foo é reatribuído (e declarado novamente na função de execução imediata, o escopo é efetivo na função de execução imediata).
console.log(foo.n)
Produto 2.
A função é executada imediatamente após a destruição, sem o escopo local foo={n: 2}
, a saída é um foo global, desta vez foo = {n: 3}; portanto, a saída 3.