다음 코드를 읽고 실행 결과를 추측하십시오.
var start = new 날짜; settimeout (function () {console.log ( 'Time Passes :'+(새 날짜 - 시작)+'msec');}, 200); while (새 날짜 - 시작 <1000) {} console.log (1); function dosoming () {settimeout (function () {console.log ( '시간이 다시 통과 :'+(새 날짜 - 시작)+'msec');} dosoming (); while (새 날짜 - 시작 <2000) {} console.log (2);나가기 :
약 1 초 후 출력 : 1,
약 1 초 후에, 출력은 다음과 같습니다.
즉시 출력 : 시간 통과 : 2002 밀리 초
마지막 출력 : 시간이 다시 통과 : 2003 밀리 초
당신은 그것을 바로 추측 했습니까?
여기서는 Settimeout으로 실행을 지연시키는 모든 기능이 실행되기 전에 끝까지 푸시됩니다.
원칙은 다음과 같습니다.
기존 브라우저 환경에서 JavaScript 실행 엔진은 단일 스레드입니다. 메인 스레드의 진술과 방법은 타이밍 작업의 실행을 차단합니다. JavaScript 실행 엔진 외부에는 작업 대기열이 있습니다. 코드에서 settimeout () 메소드가 호출되면 등록 된 지연 메소드가 브라우저 커널의 다른 모듈에 매달려 처리됩니다. 지연 메소드가 트리거 조건에 도달하면, 즉 설정 지연 시간이 세트에 도달하면 모듈은 모듈의 작업 큐에 실행될 메소드를 추가합니다. 이 프로세스는 실행 엔진의 기본 스레드와 무관합니다. 실행 엔진은 메인 스레드 메소드가 실행되고 유휴 상태에 도달 할 때 모듈의 작업 큐에서 순서대로 작업을 추출합니다. 이 기간 동안의 시간은 작업을 등록 할 때 지연 시간 설정보다 클 수 있습니다.
브라우저가 유휴 상태 인 경우, 이벤트 루프 모델이라고하는 모듈의 작업 대기열에서 작업을 지속적으로 추출하려고합니다.
이전 코드를 되돌아 보겠습니다. 두 번째 settimeout () 지연 방법의 지연 시간은 10 밀리 초이며, 첫 번째보다 일찍 트리거됩니다! 실행 결과가 뒤처지는 이유는 무엇입니까? 이전 코드에 의해 약 1000.5 ~ 1001 밀리 초 (브라우저의 처리 속도에 따라 다름), 처리 모듈에 매달려있을 때, 트리거 시간이 작업 대기열에 추가 될 때 첫 번째 설정 타임 아웃 () 지연 방법이 모듈의 작업 팀에 오랫동안 추가되었으며 메인 엔진 스레드가 오랫동안 추가되었으므로 정렬해야합니다.
이제 위의 while (새 날짜 - 시작 <1000) {}를 while (새 날짜 - 시작 <189) {} 또는 while (새 날짜 - 시작 <190) {{{{{}를 변경하면 결과는 무엇입니까? 나는 많이 말하지 않을 것입니다! 브라우저를 각각 20 번 새로 고치고 결과를 직접 확인하십시오!
setInterVal () 메소드 및 settimeout ()의 상태가 동일합니다. setInterVal () 메소드가 호출되면 등록 된 지연 메소드가 처리를 위해 모듈에 매달려 있습니다. 트리거 시간이 도착할 때마다 실행될 방법이 작업 큐에 한 번 추가됩니다.
Settimeout의 구문을 살펴 보겠습니다.
var timeid = window.settimeout (func, delay, [param1, param2, ...]);
var timeid = window.settimeout (코드, 지연);
settimeout 및 setInterval은 창 객체의 메소드입니다 (창을 생략 할 수 있음). 두 번째 선택적 매개 변수 (IE9 및 이전 버전에서 지원하지 않음)는 func로 전달되는 매개 변수입니다. 호출 할 때마다 숫자 ID가 반환됩니다 (브라우저에 인쇄 된 숫자 일뿐 아니라 WebStorm에 인쇄하여 실제로 많은 속성을 가진 객체라는 것을 알았습니다). 이 ID는 해당 Settimeout 또는 SetInterval의 관련 정보를 유지하며 주로 중간 모듈 및 작업 대기열 (Cleartimeout (ID) 및 ClearInterval (ID)을 사용하여 지우거나 닫는 데 사용됩니다.
매개 변수를 콜백 함수로 전달 해야하는 경우 다음은 IE 호환 쓰기 방법입니다.
if (document.all &&! wind window.settimeout = function (vcallback, ndelay, param1, param2, param3) {var aargs = array.prototype.slice.call (arguments, 2); __nativest __ (vcallback instanceof function? function () {vcallback.apply (null, aargs);} : vcallback, ndelay); }; window.settimeout.ispolyfill = true;}루프에서 클로저를 사용할 때 일반적인 오류가 발생합니다.
for (var i = 0; i <10; i ++) {settimeout (function () {console.log (i);}, 1000);}위의 코드는 10 번 숫자 10을 출력합니다. 왜? 폐쇄!
Console.log가 호출되면 익명 함수는 외부 변수 I에 대한 참조를 유지하지만 현재 루프는 끝났으며 I의 값은 10으로 수정됩니다.
원하는 결과를 얻으려면 각 루프에서 변수의 사본을 만들어야합니다.
루프 번호를 올바르게 얻으려면 익명 래퍼 (실제로 우리가 일반적으로 자체 실행 익명 함수라고하는 것)를 사용하는 것이 가장 좋습니다.
for (var i = 0; i <10; i ++) {(function (e) {settimeout (function () {console.log (e);}, 1000);}) (i);}외부 익명 함수는 즉시 실행되며 매개 변수로 사용됩니다. 현재 함수의 E 변수에는 i의 사본이 있습니다.
Settimeout으로 전달 된 익명 함수가 실행되면 e에 대한 참조가 있으며이 값은 루프에 의해 변경되지 않습니다.
같은 일을하는 또 다른 방법이 있습니다. 그것은 익명 래퍼에서 함수를 반환하는 것입니다. 이것은 위 코드와 동일하게 작동합니다.
for (var i = 0; i <10; i ++) {settimeout ((함수 (e) {return function () {console.log (e);}}) (i), 1000)}또 다른 중요한 응용 프로그램 : 기능 스로틀 및 기능 분비
인터넷에서 수집 한 몇 가지 정보를 참조하십시오.
JavaScript- 성능 최적화 기능 스로틀 및 기능 분비
참조 링크 :
https://developer.mozilla.org/zh-cn/docs/web/api/window/settimeout
http://www.alloyteam.com/2015/10/turning-to-javaScript-series-setmeatout-said-berevent-loop-model/#prettyphoto
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.