[javascript] <script defer =“defer”>는 정확히 어떻게 작동합니까?

몇 가지 <script>요소 가 있으며 일부 요소의 코드는 다른 <script>요소의 코드에 따라 다릅니다 . defer코드 블록이 실행에서 연기되도록 속성이 유용 할 수 있음을 보았습니다 .

그것을 테스트하기 위해 Chrome에서 이것을 실행했습니다 : http://jsfiddle.net/xXZMN/ .

<script defer="defer">alert(2);</script>
<script>alert(1)</script>
<script defer="defer">alert(3);</script>

그러나 경고합니다 2 - 1 - 3. 왜 경고하지 1 - 2 - 3않습니까?



답변

업데이트 된 날짜 : 2016 년 2 월 19 일

이 답변이 구식이라고 생각하십시오. 최신 브라우저 버전과 관련된 정보는이 게시물의 다른 답변을 참조하십시오.


기본적으로 defer는 해당 스크립트 블록에서 자바 스크립트를 실행하기 전에 브라우저가 “준비 될 때까지”기다리도록 지시합니다. 일반적으로 DOM로드 및 document.readyState == 4가 완료된 후입니다.

연기 속성은 인터넷 익스플로러에만 해당됩니다. Internet Explorer 8의 Windows 7에서 JS Fiddle 테스트 페이지에 표시되는 결과는 1-2-3입니다.

결과는 브라우저마다 다를 수 있습니다.

http://msdn.microsoft.com/en-us/library/ms533719(v=vs.85).aspx

일반적인 믿음과는 달리 IE는 사람들이 생각하는 것보다 더 자주 표준을 따릅니다. 실제로 “지연”속성은 DOM 레벨 1 사양 http://www.w3.org/TR/REC-DOM-Level-1/level에 정의되어 있습니다 . -one-html.html

W3C의 연기 정의 : http://www.w3.org/TR/REC-html40/interact/scripts.html#adef-defer :

“설정된 경우,이 부울 속성은 스크립트가 문서 컨텐츠를 생성하지 않을 것 (예 : 자바 스크립트에서”document.write “가 없음)을 사용자 에이전트에 힌트를 제공하므로 사용자 에이전트는 구문 분석 및 렌더링을 계속할 수 있습니다.”


답변

HTML5 사양의 일부 스 니펫 : http://w3c.github.io/html/semantics-scripting.html#element-attrdef-script-async

src 속성이 없으면 지연 및 비동기 속성을 지정하지 않아야합니다.


이러한 속성을 사용하여 선택할 수있는 세 가지 가능한 모드가 있습니다 [비동기 및 지연]. async 속성이 있으면 스크립트는 사용 가능한 즉시 비동기식으로 실행됩니다. 비동기 속성이 없지만 지연 속성이 있으면 페이지 구문 분석이 완료되면 스크립트가 실행됩니다. 속성이 없으면 사용자 에이전트가 페이지 구문 분석을 계속하기 전에 스크립트를 즉시 가져 와서 실행합니다.


이러한 속성에 대한 정확한 처리 세부 사항은 대부분 역사적으로 인해 HTML의 여러 측면을 포함하는 다소 사소한 것입니다. 그러므로 구현 요구 사항은 본 명세서 전반에 걸쳐 산재해야 할 필요성이있다. 아래의 알고리즘 (이 섹션에서)은이 처리의 핵심을 설명하지만 이러한 알고리즘은 HTML, 외부 콘텐츠 및 XML의 문서 규칙에 대한 스크립트 시작 및 끝 태그에 대한 구문 분석 규칙에 의해 참조되고 참조됩니다. () 방법, 스크립팅 처리 등


요소에 src 속성이 있고 요소에 지연 속성이 있고 요소가 “parser-inserted”로 플래그 지정되고 요소에 비동기 속성이없는 경우 :

요소가 작성된 구문 분석기의 문서와 연관된 문서 분석이 완료되면 실행할 스크립트 목록 끝에 요소를 추가해야합니다.


답변

진정한 답은 연기 할 수 없기 때문입니다.

개념적으로 지연 및 비동기는 다음과 같이 다릅니다.

async를 사용하면 스크립트를 차단하지 않고 백그라운드에서 다운로드 할 수 있습니다. 그런 다음 다운로드가 완료되는 순간 렌더링이 차단되고 해당 스크립트가 실행됩니다. 스크립트가 실행되면 렌더링이 다시 시작됩니다.

연기는 스크립트가 페이지에 지정된 순서대로 실행을 보장하는 주장을 제외하고, 같은 일을, 그들이 문서 후에 실행됩니다 완성 된 구문 분석이있다. 따라서 일부 스크립트는 다운로드가 완료된 후 나중에 다운로드했지만 그 앞에 나타나는 스크립트를 기다렸다가 기다릴 수 있습니다.

불행히도, 실제로 고양이 싸움의 표준으로 인해 연기자의 정의는 사양에 따라 다양하며 최신 사양에서도 유용한 보증을 제공하지 않습니다. 답변으로 여기에이 문제를 보여, 브라우저는 연기 다르게 구현 :

  • 특정 상황에서 일부 브라우저에는 defer스크립트 순서 가 잘못 되는 버그가 있습니다.
  • 일부 브라우저 DOMContentLoadeddefer스크립트가로드 될 때까지 이벤트를 지연 시키고 일부는 그렇지 않습니다.
  • 일부 브라우저는 순종 defer<script>인라인 코드와없는 요소 src속성, 일부는 그것을 무시합니다.

다행히도 스펙은 비동기 오버라이드가 지연되도록 지정합니다. 따라서 모든 스크립트를 비동기로 처리하고 다음과 같이 광범위한 브라우저 지원을 얻을 수 있습니다.

<script defer async src="..."></script>

전 세계에서 사용중인 브라우저의 98 %와 미국에서 99 %는이 접근 방식으로 차단을 피할 것입니다.

(문서 파싱이 끝날 때까지 기다려야하는 경우 이벤트 DOMContentLoaded이벤트를 듣 거나 jQuery의 편리한 .ready()기능을 사용하십시오. 어쨌든이 기능을 사용 하여 전혀 구현하지 않는 브라우저에서 정상적으로 돌아가고 싶습니다 defer.)


답변

defer외부 스크립트 포함을 <script>위해 태그 에서만 사용할 수 있습니다 . 따라서- 섹션 의 -tags에 사용하는 것이 좋습니다 .<script><head>


답변

지연 속성은 src가있는 scripts 태그에서만 작동합니다. 인라인 스크립트 지연을 모방하는 방법을 찾았습니다. DOMContentLoaded 이벤트를 사용하십시오.

<script defer src="external-script.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
    // Your inline scripts which uses methods from external-scripts.
});
</script>

지연된 스크립트가 완전히로드 된 후 DOMContentLoaded 이벤트가 발생하기 때문입니다.


답변

지연 속성은 외부 스크립트에만 사용됩니다 (src 속성이있는 경우에만 사용해야 함).


답변

script defer특정 상황에서 사용할 때 IE <= 9에 문제가있을 수 있습니다 . 자세한 내용은 https://github.com/h5bp/lazyweb-requests/issues/42