Conteúdo principal:
1. Analise o significado do escopo léxico do JavaScript
2. Analise a cadeia de variáveis do escopo
3. O que acontece quando nomes de variáveis são promovidos?
Recentemente, eu estava explicando cursos de JavaScript no Chuanzhi Podcast. Muitos amigos achavam que JavaScript era muito simples, mas não sabiam como usá-lo, então preparei algum conteúdo para compartilhar com vocês.
Esta série explica principalmente as partes avançadas do JavaScript, incluindo cadeias de escopo, fechamentos, padrões de chamada de função, protótipos e coisas orientadas a objetos. A sintaxe básica do JavaScript não está incluída aqui. : Acesse //net.itcast.cn para baixar vídeos gratuitos para aprendizado. Ok, sem mais delongas, vamos direto ao nosso tópico.
1. Sobre o escopo em nível de bloco
Falando em escopo variável do JavaScript, ele é diferente da linguagem tipo C que normalmente usamos.
Por exemplo, o seguinte código em C#:
Copie o código do código da seguinte forma:
vazio estático principal(string[] args)
{
se (verdadeiro)
{
int num = 10;
}
System.Console.WriteLine(num);
}
Se este código for compilado, ele não passará porque “o nome num não existe no contexto atual porque aqui”.
O escopo das variáveis é limitado por chaves e é chamado de escopo em nível de bloco.
No escopo em nível de bloco, todas as variáveis estão entre chaves de definição, desde o início da definição até o final das chaves.
Ele pode ser usado dentro do escopo. Não pode ser acessado fora deste escopo.
Copie o código do código da seguinte forma:
se (verdadeiro)
{
int num = 10;
System.Console.WriteLine(num);
}
É acessível aqui porque a variável é definida e usada entre as mesmas chaves.
Mas é diferente em JavaScript. Não existe conceito de escopo em nível de bloco em JavaScript.
2. Escopo em JavaScript
Em JavaScript, o seguinte código:
Copie o código do código da seguinte forma:
se(verdadeiro) {
varnum = 10;
}
alerta(núm);
O resultado da operação é uma janela pop-up 10. Então, como o escopo das variáveis é limitado em JavaScript?
2.1 Função limita o escopo da variável
Em JavaScript, apenas funções podem limitar o escopo de uma variável.
Ou seja, em JavaScript, variáveis definidas dentro de uma função podem ser acessadas dentro da função, mas fora da função
Não foi possível acessar. Veja o seguinte código:
Copie o código do código da seguinte forma:
var função = função() {
varnum = 10;
};
tentar {
alerta(núm);
} pegar (e) {
alerta(e);
}
Quando este código for executado, uma exceção será lançada e a variável num não será definida. Em outras palavras, a variável definida na função não pode.
Usado fora da função, claro que pode ser usado livremente dentro da função, mesmo antes da atribuição. Veja o código a seguir:
Copie o código do código da seguinte forma:
var função = função() {
alerta(núm);
varnum = 10;
alerta(núm);
};
tentar {
função();
} pegar (e) {
alerta(e);
}
Depois que esse código for executado, nenhum erro será gerado e a janela pop-up aparecerá duas vezes, indefinido e 10 (explicarei o motivo abaixo).
Pode-se ver aqui que as variáveis só podem ser acessadas dentro de uma função. Da mesma forma, as funções dentro da função também podem ser acessadas.
2.2 Subdomínio acessa domínio pai
Conforme mencionado anteriormente, uma função pode limitar o escopo de uma variável, então a função na função se torna um subdomínio do escopo no subdomínio.
O código em pode acessar variáveis no domínio pai. Veja o código a seguir:
Copie o código do código da seguinte forma:
var função = função() {
varnum = 10;
var sub_func = função() {
alerta(núm);
};
sub_func();
};
função();
O resultado da execução deste código é 10. Você pode ver o acesso à variável mencionado acima, mas ao acessar o domínio pai no domínio filho.
O código também é condicional, como o seguinte código:
Copie o código do código da seguinte forma:
var função = função() {
varnum = 10;
var sub_func = função() {
varnum = 20;
alerta(núm);
};
sub_func();
};
função();
Este código tem mais um "var num = 20;" do que antes. Este código está no subdomínio, então o subdomínio acessará o domínio pai.
Houve uma mudança, o resultado impresso por este código é 20. Ou seja, o num acessado pelo subdomínio neste momento é uma variável do subdomínio, não do domínio pai.
Pode-se observar que existem certas regras de acesso. Ao usar variáveis em JavaScript, o interpretador JavaScript primeiro.
Pesquise no domínio do usuário para ver se existe uma definição da variável. Em caso afirmativo, use esta variável; caso contrário, procure a variável no domínio pai.
Por analogia, até que o escopo de nível superior ainda não seja encontrado, uma exceção "variável não definida" será lançada. Veja o código a seguir:
Copie o código do código da seguinte forma:
(função() {
varnum = 10;
(função() {
varnum = 20;
(função(){
alerta(núm);
})()
})();
})();
Após a execução deste código, 20 será impresso. Se "var num = 20;" for removido, 10 será impresso da mesma forma, se for removido novamente.
"var num = 10", ocorrerá um erro indefinido.
3. Cadeia de escopo
Com a divisão dos escopos JavaScript, os escopos de acesso JavaScript podem ser conectados em uma estrutura de árvore encadeada.
Uma vez que a cadeia de escopo do JavaScript possa ser claramente compreendida, as variáveis e fechamentos do JavaScript ficarão muito claros.
O método a seguir usa desenho para desenhar a cadeia de escopo.
3.1 Regras de desenho:
1) A cadeia de escopo é uma matriz de objetos
2) Todos os scripts são cadeias de nível 0, cada objeto ocupa uma posição
3) Sempre que você vir uma função se estendendo em uma cadeia, expanda-a nível por nível.
4) Ao acessar, primeiro observe a função atual. Caso não esteja definida, verifique a cadeia.
5) Repita isso até a cadeia do nível 0
3.2 Exemplos
Veja o código abaixo:
Copie o código do código da seguinte forma:
varnum = 10;
var func1 = função() {
varnum = 20;
var func2 = função() {
varnum = 30;
alerta(núm);
};
func2();
};
var func2 = função() {
varnum = 20;
var func3 = função() {
alerta(núm);
};
func3();
};
func1();
func2();
Vamos analisar este código:
-> Em primeiro lugar, todo o código é um escopo global e pode ser marcado como uma cadeia de escopo de nível 0. Depois, há um array.
var link_0 = [ num, func1, func2 ]; // Descrito aqui com pseudocódigo
-> Aqui func1 e func2 são funções, portanto, duas cadeias de escopo de nível 1 são derivadas, a saber
var link_1 = { func1: [ num, func2 ] }; // Descrito aqui com pseudocódigo
var link_1 = { func2: [ num, func3 ] }; // Descrito aqui com pseudocódigo
-> A primeira cadeia de nível 1 deriva da cadeia de nível 2
var link_2 = { func2: [ num ] }; // Descrito aqui com pseudocódigo
-> A cadeia do segundo nível 1 não possui variáveis definidas e é uma cadeia vazia, que é expressa como
var link_2 = { func3: [ ] };
-> Ao integrar o código acima, a cadeia de escopo pode ser expressa como:
Copie o código do código da seguinte forma:
//Descrito aqui com pseudocódigo
var link = [ // cadeia de nível 0
num,
{ func1: [ // A primeira cadeia de nível 1
num,
{ func2: [ // cadeia de nível 2
número
] }
]},
{ func2: [ // A cadeia do segundo nível 1
num,
{ func3: [] }
]}
];
-> Representado como uma imagem como
Figura: 01_01 escopo chain.bmp
Nota: Use o código js para expressar o diagrama de cadeia, e ele ficará muito claro quando destacado.
Com este diagrama de cadeia de escopo, você pode entender claramente como é realizado o acesso às variáveis:
Quando você precisar usar uma variável, primeiro procure a variável na cadeia atual. Se você encontrá-la, use-a diretamente.
Pesquise para cima; se não for encontrado, pesquise para cima na cadeia de escopo de um nível até a cadeia de escopo de nível 0.
Se você puder determinar claramente o nível da cadeia de escopo ao qual uma variável pertence, então, ao analisar JavaScript
É muito fácil quando se trata de codificação e uso de recursos avançados de JavaScript, como encerramentos (pelo menos para mim).
3. Promoção de nome de variável e promoção de nome de função
Com a cadeia de escopo e as regras de acesso a variáveis, há um problema muito difícil. Vejamos primeiro o seguinte.
Código JavaScript:
Copie o código do código da seguinte forma:
varnum = 10;
var função = função() {
alerta(núm);
varnum = 20;
alerta(núm);
};
função();
Qual será o resultado da execução? Você pode pensar sobre isso, não vou revelar a resposta ainda.
Vamos analisar este código primeiro.
Há uma cadeia de escopo de nível 0 neste código, que contém os membros num e func. Em func, há uma função de nível 1.
Cadeia de domínio, que contém o membro num. Portanto, quando a função func for chamada, ela será detectada no escopo atual.
A variável num foi definida, então esta variável será usada. No entanto, num não recebeu um valor neste momento, devido ao código.
O código é executado de cima para baixo. Portanto, a primeira impressão é indefinida e a segunda impressão é 20.
Você acertou?
Também é comum em JavaScript definir o código atrás e usá-lo na frente assim
Pergunta Neste momento, é como se a variável tivesse sido definida no início, e o resultado é como o seguinte código:
Copie o código do código da seguinte forma:
varnum = 10;
var função = função() {
var num;// Parece que foi definido aqui, mas não há atribuição.
alerta(núm);
varnum = 20;
alerta(núm);
};
função();
Este fenômeno é frequentemente chamado de promoção de nome de variável. Há também promoção de nome de função. Por exemplo, o seguinte código:
Copie o código do código da seguinte forma:
var função = função() {
alert("Chamar função externa");
};
var foo = função() {
função();
var função = função() {
alert("Chamar função interna");
};
função();
};
Ok, como é esse código? Ou deveria haver algo diferente, não vou deixar que os leitores pensem!
Darei a resposta no próximo artigo.
Devido a estas diferenças, durante o desenvolvimento real, é recomendado escrever todas as variáveis no início.
Ou seja, as variáveis são definidas no início da função, semelhante ao disposto na linguagem C. Isso também vale nas bibliotecas js.
Isso é feito, como jQuery, etc.
4. Resumo
Ok, este artigo explica principalmente do que se trata o escopo léxico do JavaScript e sua explicação.
Como analisar a cadeia de escopo e o status de acesso às variáveis, vamos deixar um último exercício para finalizar! ! !
Veja qual é o resultado da execução do código abaixo:
Copie o código do código da seguinte forma:
if( ! "a" na janela ) {
var a = "definir variável";
}
alerta(a);