Leia o seguinte código e adivinhe o resultado da execução:
var start = new Date; setTimeout (function () {console.log ('tempo passa:'+(nova data - start)+'msec');}, 200); while (nova data - iniciar <1000) {} console.log (1); function Dosoming () {setTimeout (function () {console.log ('O tempo passa novamente:'+(nova data - start)+'msec');}, 10);} dossoming (); while (nova data - iniciar <2000) {} console.log (2);vire para fora:
Saída após cerca de 1 segundo: 1,
Após cerca de 1 segundo, a saída é: 2.
Em seguida, imediatamente a saída: tempo passado: 2002 milissegundos
Última saída: tempo passado novamente: 2003 milissegundos
Você adivinhou certo?
Aqui, todas as funções que atrasam a execução do setTimeout são empurradas até o fim antes da execução;
O princípio é o seguinte:
No ambiente do navegador existente, o mecanismo de execução do JavaScript é um único thread. As declarações e métodos do thread principal bloquearão a execução das tarefas de tempo. Fora do mecanismo de execução JavaScript, há uma fila de tarefas. Quando o método setTimeout () for chamado no código, o método de atraso registrado será pendurado em outros módulos no kernel do navegador para processamento. Quando o método de atraso atinge a condição do gatilho, ou seja, o tempo de atraso do conjunto atinge o conjunto, o módulo adicionará o método a ser executado à fila de tarefas do módulo. Esse processo é independente do encadeamento principal do mecanismo de execução. O mecanismo de execução extrairá tarefas da fila de tarefas do módulo em sequência para executar quando o método principal do encadeamento é executado e atinge o estado ocioso. O tempo durante esse período pode ser maior que o tempo de atraso definido ao registrar a tarefa;
Quando o navegador estiver ocioso, ele tentará constantemente extrair tarefas da fila de tarefas do módulo, que é chamada de modelo de loop de eventos;
Vamos olhar para o código anterior. O tempo de atraso do segundo método de atraso setTimeout () é de 10 milissegundos, que é acionado antes do primeiro! Por que o resultado da execução está para trás? Because it was blocked by the previous code for about 1000.5~1001 milliseconds (depending on the browser's processing speed), when it hangs to the processing module and when the trigger time is added to the task queue, the first setTimeout() delay method has long been added to the module's task team, and the main engine thread is obtained in order, so, you should understand, right?
Agora, se você alterar o acima (nova data - iniciar <1000) {} para while (nova data - iniciar <189) {} ou while (nova data - start <190) {}, qual é o resultado? Eu não vou dizer muito! Atualize o navegador 20 vezes cada e veja os resultados!
O método setInterval () e setTimeout () têm o mesmo status. Quando o método setInterval () é chamado, o método de atraso registrado é pendurado no módulo para processamento. Sempre que o tempo de gatilho chega, o método a ser executado é adicionado à fila de tarefas uma vez;
Vamos dar uma olhada na sintaxe do setTimeout:
var timeId = window.setTimeout (func, atraso, [param1, param2, ...]);
var timeId = window.setTimeout (código, atraso);
Settimeout e SetInterval são métodos de objetos de janela (a janela pode ser omitida). Os segundos parâmetros opcionais (não suportados pelo IE9 e versões antigas) são parâmetros passados para o FUNC. Cada vez que são chamados, um ID numérico será devolvido (é apenas um número impresso no navegador, mas eu o imprimi na Webstorm e descobri que na verdade é um objeto com muitos atributos). Esse ID mantém as informações relevantes de sua correspondente Settimeout ou SetInterval e é usada principalmente para limpar (ou fechar) no módulo intermediário e na fila de tarefas (usando os métodos ClearTimeout (ID) e ClearInterval (ID)).
Se você precisar passar um parâmetro para sua função de retorno de chamada, o seguinte é o método de escrita compatível com o IE
if (document.all &&! window.settimeout.ispolyfill) {var __nativest__ = window.setTimeout; window.setTimeout = function (vcallback, ndelay, param1, param2, param3) {var aargs = array.prototype.slice.call (argumentos, 2); return __nativest __ (vcallback instanceof function? function () {vcallback.apply (null, aargs);}: vcallback, ndelay); }; window.setTimeout.ispolyfill = true;}Um erro comum ocorre ao usar o fechamento em um loop
for (var i = 0; i <10; i ++) {setTimeout (function () {console.log (i);}, 1000);}O código acima produzirá o número 10 dez vezes. Por que? Encerramento!
Quando o console.log é chamado, embora a função anônima mantenha uma referência à variável externa i, o loop for terminou neste momento e o valor de I é modificado em 10.
Para obter o resultado desejado, uma cópia da variável que eu preciso ser criada em cada loop.
Para obter o número do loop corretamente, é melhor usar um invólucro anônimo (na verdade, o que geralmente chamamos de funções anônimas auto-executadas).
for (var i = 0; i <10; i ++) {(function (e) {setTimeout (function () {console.log (e);}, 1000);}) (i);}A função anônima externa será executada imediatamente e eu serei usado como seu parâmetro. Neste momento, a variável E na função terá uma cópia de i.
Quando a função anônima passada para o setTimeout é executada, ela tem uma referência a E e esse valor não será alterado pelo loop.
Há outra maneira de fazer o mesmo trabalho; Isso é para devolver uma função de um invólucro anônimo. Isso funciona da mesma forma que o código acima.
for (var i = 0; i <10; i ++) {setTimeout ((function (e) {return function () {console.log (e);}}) (i), 1000)}Outra aplicação importante: o acelerador de funções e o debounce da função
Por favor, veja algumas informações que coletei da Internet:
JavaScript - Função de otimização de desempenho acelerador e debounce de funções
Link de referência:
https://developer.mozilla.org/zh-cn/docs/web/api/window/settimeout
http://www.alloyteam.com/2015/10/turning-to-javascript-series-from-settimeout-said-the-event-loop-model/#prettyphoto
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.