Da definição à execução, o mecanismo JS faz muitos trabalhos de inicialização na camada de implementação. Portanto, antes de aprender o mecanismo de trabalho do mecanismo JS, precisamos introduzir vários conceitos relacionados: pilha de ambiente de execução, objetos globais, ambiente de execução, objetos variáveis, objetos ativos, cadeias de escopo e escopo, etc. Esses conceitos são os principais componentes do trabalho do mecanismo JS. O objetivo deste artigo não é explicar cada conceito para você isoladamente, mas analisá -lo através de uma demonstração simples, explicando os detalhes do mecanismo JS da definição à execução e o papel que esses conceitos desempenham nele.
var x = 1; // Defina uma variável global xfunction a (y) {var x = 2; // Defina uma variável local Função x B (z) {// Defina uma função interna b console.log (x+y+z); } retornar b; // retorna uma referência à função b} var c = a (1); // execute a, retorno bc (1); // Execute a função bEsta demonstração é um fechamento e o resultado da execução está 4. Abaixo, analisaremos o mecanismo de trabalho do mecanismo JS em três estágios: inicialização global, função de execução A e função de execução B :
1. Inicialização global
Quando o mecanismo JS entra em um código executável, ele precisa concluir as três tarefas de inicialização a seguir:
Primeiro, crie um objeto global (objeto global). Existe apenas uma cópia global desse objeto, suas propriedades podem ser acessadas em qualquer lugar e sua existência acompanhará todo o ciclo de vida do aplicativo. Ao criar um objeto global, objetos JS comumente usados, como matemática, string, data, documento, são usados como suas propriedades. Como esse objeto global não pode ser acessado diretamente pelo nome, há outra janela de propriedades e aponta a janela para si mesma, para que o objeto global possa ser acessado através da janela. A estrutura geral do uso do código pseudo para simular objetos globais é a seguinte:
// Crie um objeto global var globalObject = {Math: {}, String: {}, Date: {}, documento: {}, // operação dom ... Janela: this // Deixe o atributo da janela apontar para si mesmo}Em seguida, o mecanismo JS precisa criar uma pilha de contexto de execução. Ao mesmo tempo, ele também precisa criar um contexto de execução global EC e empurrar esse ambiente de execução global CE para a pilha de ambiente de execução. A função da pilha de ambiente de execução é garantir que o programa possa ser executado na ordem correta. No JavaScript, cada função possui seu próprio ambiente de execução. Ao executar uma função, o ambiente de execução da função será empurrado para o topo da pilha do ambiente de execução e obterá direitos de execução. Quando essa função é executada, seu ambiente de execução é excluído da parte superior da pilha e o direito de execução é devolvido ao ambiente de execução anterior. Usamos o pseudocódigo para simular a relação entre a pilha de ambiente de execução e a CE:
var ecstack = []; // Defina uma pilha de ambiente de execução, semelhante à matriz var EC = {}; // Crie um espaço de execução, // A especificação ECMA-262 não define claramente a estrutura de dados da CE, você pode entendê-lo como uma peça de espaço alocada no ecstack.push (CE); // Digite a função e empurre o ambiente de execução Ecstack.pop (CE); // Depois que a função retornar, exclua o ambiente de execuçãoFinalmente, o mecanismo JS também cria um objeto variável global (objeto Varibale) Vo associado à CE e pontos Vo para o objeto global. O VO não apenas contém as propriedades originais do objeto global, mas também inclui a variável x e a função A definido globalmente. Ao mesmo tempo, ao definir a função A, um escopo de atributo interno também é adicionado a um escopo de pontos e pontos ao VO. Quando cada função é definida, um atributo de escopo associado a ele será criado e o escopo sempre aponta para o ambiente em que a função é definida. A estrutura de Ecstack neste momento é a seguinte:
ECSTACK = [// Pilha de ambiente de execução Ec (g) = {// Ambiente de Execução Global Vo (G): {// Definir Objeto Global Variável ... // Contém os atributos originais do objeto global x = 1; // define variável x a = function () {...}; // define função aa [[escopo]] = this; // Defina o escopo de A e atribua valor a Vo em si}}];2. Execute a função A
Quando a execução entra em um (1), o motor JS precisa fazer o seguinte:
Primeiro, o mecanismo JS criará o ambiente de execução EC da função A e, em seguida, a CE o empurrará para o topo da pilha do ambiente de execução e obterá os direitos de execução. No momento, existem dois ambientes de execução no ambiente de execução, a saber, o ambiente de execução global e a função de um ambiente de execução. O ambiente de execução de A está no topo da pilha e o ambiente de execução global está na parte inferior da pilha. Em seguida, crie a cadeia de função do escopo A. No JavaScript, cada ambiente de execução possui sua própria cadeia de escopo para resolução de identificador. Quando o ambiente de execução é criado, sua cadeia de escopo é inicializada como o objeto contido no escopo da função atualmente em execução.
Em seguida, o mecanismo JS criará um objeto ativo (objeto de ativação) AO da função atual. O objeto ativo aqui desempenha o papel de um objeto variável, mas é chamado de maneira diferente na função (você pode pensar que um objeto variável é um conceito geral, e o objeto ativo é um ramo). AO contém os parâmetros formais da função, o objeto de argumentos, esse objeto, bem como as definições de variáveis locais e funções internas, e depois a AO será empurrada para o topo da cadeia de escopo. Deve -se notar que, ao definir a função B, o mecanismo JS também adicionará um atributo de escopo ao escopo B e apontar ao ambiente em que a função B é definida. O ambiente em que a função B é definida é o objeto ativo AO da A, e AO está localizado na extremidade frontal da lista vinculada. Como a lista vinculada possui as características da conexão final, o escopo da função B aponta para toda a cadeia de escopo de A. Vamos dar uma olhada na estrutura da Ecstack neste momento:
ECSTACK = [// Pilha de ambiente de execução Ec (a) = {// Ambiente de execução de A [Escopo]: vo (g), // VO é o objeto variável global AO (a): {// Crie o objeto ativo y: 1, x: 2, // define a variável local x b: function () {...}, // //This refers to AO itself, and AO is at the top of scopeChain, so B[[scope]] points to the entire scope chain arguments:[],//The arguments we access in the function are arguments in AO this:window //This in the function points to the caller window object}, scopeChain:<AO(A),A[[scope]]> //The linked list is initialized as A[[scope]], and Em seguida, AO é adicionado ao topo da corrente do escopo. Neste momento, a cadeia de escopo de A: AO (a)-> vo (g)}, ec (g) = {// ambiente de execução global vo (g): {// cria objeto variável global ... // contém os atributos originais do objeto global x = 1; // define a variável x a = function () {...}; // Defina a função AA [[SCOPE]] = this; // define o escopo de A, a [[escopo]] == vo (g)}}];3. Execute a função B
Após a execução da função A, a referência a B é retornada e atribuída à variável C. A execução de C (1) é equivalente à execução de B (1). O mecanismo JS precisa concluir as seguintes tarefas:
Primeiro, como acima, crie o ambiente de execução EC da função B e depois empurre o CE para o topo da pilha de ambiente de execução e obtenha os direitos de execução. No momento, existem dois ambientes de execução no ambiente de execução, a saber, o ambiente de execução global e o ambiente de execução da função B. O ambiente de execução de B está no topo da pilha, e o ambiente de execução global está na parte inferior da pilha. (Nota: Quando a função A retorna, o ambiente de execução de A será excluído da pilha, deixando apenas o ambiente de execução global), crie a cadeia de escopo da função B e a inicialize no objeto contido no escopo da função B, ou seja, a cadeia de escopo de A. Finalmente, crie o objeto ativo da função B e use os parâmetros. Neste momento, a Ecstack se tornará assim:
ECStack = [ //Execution environment stack EC(B) = { //Create B's execution environment and is at the top of the scope chain [scope]:AO(A), //Point to the scope chain of function A, AO(A)->VO(G) var AO(B) = { //Create the active object of function B z:1, arguments:[], this:window } ScopeCHAIN: <AO (B), B [[SCOPE]]> // A lista vinculada é inicializada para B [[SCOPE]] e, em seguida, AO (B) é adicionado ao cabeçalho da lista vinculada. Neste momento, a cadeia de escopo de B: AO (b)-> AO (a) -Vo (g)}, ec (a), // o ambiente de execução de A foi excluído da parte superior da pilha, EC (g) = {// Ambiente global de Execução Global Vo: {// Definy Variable Global ... // contém os Attributes do Global Object X; // define variável x a = function () {...}; // define função aa [[escopo]] = this; // define o escopo de a, a [[escopo]] == vo (g)}}];Quando a função B executa "x+y+z", é necessário analisar os três identificadores x, y e z um por um. O processo de análise adere às regras de pesquisa variável: primeiro encontre se o atributo existe em seu objeto ativo. Se existir, pare de pesquisar e retorne; Se não existir, continue pesquisando de cima ao longo de sua corrente de escopo, até que seja encontrada. Se a variável não for encontrada em toda a corrente do escopo, retorne "indefinido". A partir da análise acima, podemos ver que a cadeia de escopo da função B é a seguinte:
Ao (b)-> Ao (a)-> vo (g)
Portanto, a variável x será encontrada em AO (a) e não procurará x em vo (g), a variável y será encontrada em AO (a) e a variável z será encontrada em seu próprio AO (B). Portanto, o resultado da execução: 2+1+1 = 4.
Resumo simples
Depois de entender o mecanismo de trabalho do mecanismo JS, não podemos simplesmente permanecer no nível de compreensão do conceito, mas usá -lo como uma ferramenta básica para otimizar e melhorar nosso código no trabalho real, melhorar a eficiência da execução e gerar valor real. Pegue o mecanismo de pesquisa variável como exemplo. Se o seu código estiver profundamente aninhado e toda vez que você se referir a uma variável global, o mecanismo JS procurará toda a cadeia de escopo. Por exemplo, existe esse problema com os objetos de janela e documento na parte inferior da cadeia do escopo. Portanto, podemos fazer muita otimização de desempenho em torno desse problema e, é claro, existem outros aspectos das otimizações. Não vou entrar em detalhes aqui. Este artigo é considerado uma dica!
por @一竞 2015
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.