[21] [CODE(HTMLe)@en[[[script]]]] [[要素]]の [DFN[[CODE(HTMLa)@en[[[defer]]]]]]
[[属性]]は、[[構文解析]]が完了してから[[スクリプト]]を実行するべきことを表します。

* 仕様書

[REFS[
- [6] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2016-02-16 01:30:20 +09:00]] 版) <https://html.spec.whatwg.org/#the-script-element>
-- [7] '''[CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2016-02-21 07:50:23 +09:00]] 版) <https://html.spec.whatwg.org/#attr-script-defer>'''
]REFS]

* 意味

[8] [CODE(HTMLa)@en[[[defer]]]] [[属性]]は、
[[スクリプト]]がどう処理されるべきかを指定するものです。 [SRC[>>7]]

[10] [CODE(HTMLe)@en[[[script]]]] [[要素]]の種別が[[古典スクリプト]]の場合で、
[CODE(HTMLa)@en[[[async]]]] [[属性]]が指定されない場合には、
[CODE(HTMLa)@en[[[defer]]]] [[属性]]が指定されると、
[[構文解析]]と[[並列に]] [[fetch]] が行われ、
[[構文解析]]が完了してから評価されます。
[CODE(HTMLa)@en[[[async]]]] [[属性]]も [CODE(HTMLa)@en[[[defer]]]]
[[属性]]も指定されない場合には、 [[fetch]] と評価が直ちに行われ、
その後[[構文解析]]が再開されます。 [SRC[>>7]]

* 属性値

[3] [CODE(HTMLa)@en[[[defer]]]] [[属性]]は、[[ブール型属性]]です。

* 文脈

[12] [CODE(HTMLe)@en[[[script]]]] [[要素]]の種別が[[古典スクリプト]]で、
[CODE(HTMLa)@en[[[async]]]] [[属性]]が指定されていない時、
[CODE(HTMLa)@en[[[defer]]]] [[属性]]が効果を持ちます。

[17] [CODE(HTMLa)@en[[[defer]]]] [[属性]]は、 [CODE(HTMLa)@en[[[async]]]]
[[属性]]が指定されている場合であっても、 [CODE(HTMLa)@en[[[async]]]]
未対応の[[利用者エージェント]]での動作を考慮して、指定することができます [SRC[>>7]]。
しかしどの [[Webブラウザー]]も [CODE(HTMLa)@en[[[async]]]]
に対応した現在となっては、その必要ももう無さそうです。

[13] [CODE(HTMLe)@en[[[script]]]] [[要素]]の種別が[[モジュールスクリプト]]の時は、
[CODE(HTMLa)@en[[[defer]]]] [[属性]]は効果を持ちません [SRC[>>7]]。

;; [18] [[モジュールスクリプト]]の時は、常に [CODE(HTMLa)@en[[[defer]]]]
を指定した[[古典スクリプト]]相当の動作となります。

[9] [CODE(HTMLe)@en[[[script]]]] [[要素]]の種別が[[データブロック]]の時は、
[CODE(HTMLa)@en[[[defer]]]] [[属性]]を使っては[['''なりません''']] [SRC[>>6]]。

* 処理

[11] [CODE(HTMLe)@en[[[script]]]] を参照。

[25] なお、初回処理時の値が使われるので、動的に変更しても、意味を持ちません [SRC[>>7]]。

* [CODE(DOMi)@en[HTMLScriptElement]] インターフェイス [CODE(DOMa)@en[defer]] 属性

[29] [CODE(DOMi)@en[[[HTMLScriptElement]]]] [[インターフェイス]]の
[DFN[[CODE(DOMa)@en[[[defer]]]]]] [[IDL属性]]は、
[CODE(HTMLa)@en[[[defer]]]] [[内容属性]]を[[反映]]しなければ[['''なりません''']]
[SRC[>>6]]。これは[[ブール値]]として[[反映]]するものです。

* 歴史

** HTML4

[15] [[HTML4]] 時代には [CODE(HTMLa)@en[[[defer]]]] [[属性]]は定義こそされていましたが、
[[スクリプト]]の処理モデル自体が規定されていないため仕様書の説明もほとんど意味不明でした。
そのためか世間に流布している解説の類も混乱していました。唯一 [[IE]]
が実装していましたが、それが仕様書と合致しているのかもよくわからない状況でした。

[1] [[HTML]] の [CODE(HTMLe)[[[script]]]] 要素の
[DFN[[CODE(HTMLa)[defer]] 属性]]は、
そのスクリプトが文書内容を生成しないことを示します。

[2] 仕様書:
- [[HTML 4]]
-- <IW:HTML4:"interact/scripts.html#adef-defer">

[22]
HTML 4 DTD の[[注釈]] (参考) には
[Q[UA may defer execution of script]]
と書かれています。

[4] この属性が指定されていると、そのスクリプトが文書の内容を生成しないことを意味します。
[[JavaScript]] の [CODE(JS)[[[document]].[[write]]]] が文書内容生成に該当します。
UA はこの属性が指定されていれば、構文解析とレンダリングを続行できます。
[SRC[HTML 4 18.2.1]]

[14] 仕様書は当たり前だと思って書いていないのでしょうが、
文書を読み込みながら構文解析しながらスクリプトを実行しつつレンダリングするという処理モデルが念頭にあるのだと思われます。
レンダリングする文書の内容は普通は鯖から送られてきたものですが、
[CODE(HTMLe)[script]] 要素によって動的に生成されるかもしれません。
ですから、 [CODE(HTMLe)[script]] 要素まで読取り・構文解析・レンダリングが到達したら、
そのスクリプトを実行して結果を反映して続きの構文解析・レンダリングを行わなければなりません。
しかし、スクリプトの内容が関数の定義や[[事象取扱器]]の登録なら、
その時点で行う必要はありません。そこで [CODE(HTMLa)[defer]]
と指定しておけば、 UA は文書全体をレンダリングしてから実行することができます。

[23]

> Indicates that the user agent can defer processing of the script. See the defer attribute definition  in HTML 4.0.

;; 
<IW:DOM1:"level-one-html.html#ID-93788534">

[24]

> Indicates that the user agent can defer processing of the script. See the defer attribute definition in HTML 4.01.

;; 
<IW:DOM2:"HTML/html.html#ID-93788534">

[FIG(quote)[
[FIGCAPTION[
[19] ''JavaScript質問スレ'' <http://pc2.2ch.net/test/read.cgi/hp/1041701828/701->
]FIGCAPTION]

> 703 名前: Name_Not_Found  投稿日: 03/01/31 21:13 ID:???
[PRE[
defer
【誤答例】
スクリプトに文書の表示を生成する要素を含まないことを宣言します。
この要素内のスクリプトが、文書の内容となるものを一切生成しない
(例えば、"document.write" などを使用していない)ことを表わします。
【正答例】
ブロック内にインラインスクリプトがなく、関数だけを含んでいることを示す。
スクリプトが必要になるまでその解析を延期することにより、
ドキュメントのロード時間が短くなり、結果的にパフォーマンスが良くなる
]PRE]
> 704 名前: Name_Not_Found 投稿日: 03/01/31 22:08 ID:???
[PRE[
>>703
http://www.w3.org/TR/1999/REC-html401-19991224/interact/scripts.html#adef-defer
http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/defer.asp
http://www.microsoft.com/japan/developer/library/jpisdk/dhtml/references/html/SCRIPT.htm
つまり誤答例の HTML4 Spec. はウ゛ァカ仕様で
「関数だけを含む」と書いてないMSDN本家も厨房マニュアルで
正答例のMSDN日本語版スハ゛ラシイ!ってことでよろしいか? 
]PRE]
]FIG]

[20]
[CITE[ishinao.net/mylog - deferとWScript.Shell.Runの第3引数]] <http://mylog.ishinao.net/id/1190>

[26] >>20 は [CODE(HTTP)[[[404]]]] なので...

[CITE[ishinao.net/mylog - deferとWScript.Shell.Runの第3引数]] <http://web.archive.org/web/20050302231327/http://mylog.ishinao.net/id/1190>

>
[PRE(example code)[
<script type="text/javascript" defer>
var shell = new ActiveXObject("WScript.Shell");
shell.run("notepad.exe", 1, true);
alert("end");
</script>
]PRE]
> みたいなスクリプトで、shell.runの第3引数がtrue(終了するまで待つ)になっているのが効かないのはどうしてだろう? よりローカルな設定ほど強力であるというのが一般的だと思うんだけど、defer設定は何よりも強力ってことなのかなー。

いってることがよくわからない。

** HTML5

[27]
[[Ian Hickson]] は当初 [CODE(HTMLa)@en[[[defer]]]]
は相互運用可能に実装されていないとして [[HTML 5]]
に含めないつもりだったようです (たぶん。) が、結局
[CODE(HTMLa)@en[[[src]]]] が指定されている場合にのみ利用できる[[属性]]として
[[HTML 5]] に残りました。

[16] [[HTML5]] が初めて[[スクリプト]]の明確な処理方法を定義し、
そこに [CODE(HTMLa)@en[[[defer]]]] [[属性]]の規定も含めたことで、
ようやく [[IE]] 以外の [[Webブラウザー]]もこれを実装できるようになりました。

[28]
[CITE@ja[「週報」を含むエントリー - Buzzurl '''['''バザール''']''' / ソーシャルブックマーク]] ([TIME[2008-06-08 00:26:54 +09:00]] 版) <http://buzzurl.jp/tag/%E9%80%B1%E5%A0%B1>

[PRE(HTML example code)[
<script type="text/javascript" defer="defer">
	<!--
(function(){
	var date = new Date();
	date.setTime(date.getTime() + (24*60*60*1000));
	var expires = '; expires=' + date.toGMTString();
	document.cookie = 'is_ssl=1' + expires + '; path=/; secure';
})();

(function(){
 	function beforeChange(container, active){
		if(!active){ return; }
		var bef = $(active).getAttribute("rel");
		if(!bef){ return; }
		var def = container.options.afterChange;
		container.options.afterChange = function(t,a){
			var aft = $(a).getAttribute("rel");
			if(aft){
				$(aft).value = $F(bef);
			}
			def(t,a);
			t.options.afterChange = def;
		};
	}
	Event.observe(window,'load',function(){
		new Control.Tabs($("search_tab_list"), {"defaultTab":'form_buzzurl', "beforeChange":beforeChange});
	});
})();
function gnJoin(done, caption){
	if(done){ document.join_form.done.value = done; }
	if(caption){ document.join_form.caption.value = caption; }
	document.join_form.submit();
}
-->
</script> 
]PRE]

[405] [CITE@en-us[Firefox 3.1 for developers - MDC]] ([TIME[2009-02-08 18:25:06 +09:00]] 版) <https://developer.mozilla.org/ja/Firefox_3.1_for_developers#HTML_.e3.81.ae.e5.a4.89.e6.9b.b4.e7.82.b9>

>script 要素の defer 属性のサポートが実装されました。

[406] [CITE[script要素のdefer属性の実装 - Thousand Years]] ([TIME[2009-02-03 20:39:32 +09:00]] 版) <http://d.hatena.ne.jp/shogo4405/20070306/1173160753>

[407] [CITE[Firefox_3.5_for_developers#Miscellaneous_new_features]] (Referenced: [TIME[2009-07-12T21:29:47+09:00]])
<https://developer.mozilla.org/en/Firefox_3.5_for_developers#Miscellaneous_new_features>


[408] [CITE@en[(X)HTML5 Tracking]]
([TIME[2009-08-08 01:13:50 +09:00]] 版)
<http://html5.org/tools/web-apps-tracker?from=3549&to=3550>

[409] [CITE[IRC logs: freenode / #whatwg / 20090721]]
([TIME[2009-09-26 21:27:34 +09:00]] 版)
<http://krijnhoetmer.nl/irc-logs/whatwg/20090721>

[410] [CITE[IRC logs: freenode / #whatwg / 20090807]]
([TIME[2009-10-06 00:19:08 +09:00]] 版)
<http://krijnhoetmer.nl/irc-logs/whatwg/20090807>

[411] [CITE@en[(X)HTML5 Tracking]]
([TIME[2009-10-10 02:56:30 +09:00]] 版)
<http://html5.org/tools/web-apps-tracker?from=4097&to=4098>

[412] [CITE[IRC logs: freenode / #whatwg / 20100118]]
([TIME[2010-01-20 07:35:37 +09:00]] 版)
<http://krijnhoetmer.nl/irc-logs/whatwg/20100118#l-426>

[413] [CITE[IRC logs: freenode / #whatwg / 20130528]]
( ([TIME[2013-05-29 23:52:26 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20130528>

** モジュールスクリプトの導入

[5] [CITE@en[Add <script type="module"> and module resolution/fetching/evaluation · whatwg/html@cd1a9fb]]
([TIME[2016-01-21 22:16:10 +09:00]] 版)
<https://github.com/whatwg/html/commit/cd1a9fb1e83f7d0bc30be8b34ecdaf444a0b19a4>

[30] [CITE@en[(Re)disallow script defer/async attributes w/o src]]
([[sideshowbarker]]著, [TIME[2017-04-05 21:04:55 +09:00]])
<https://github.com/whatwg/html/commit/3c5180a08f90a375c64f8191f32f8c7ddfec0ba3>

[31] [CITE@en[Unclear whether setting defer attribute on script tags guarantees execution in document order · Issue #3176 · whatwg/html]]
([TIME[2017-11-22 20:49:17 +09:00]])
<https://github.com/whatwg/html/issues/3176>