JavaScript初心者脱却計画(addEventListenerについて)
このnoteは、JavaScript初心者脱却を目指すものです。(前回投稿はこちら)
※メイン参考書は引き続き「ノンプログラマのためのJavaScriptはじめの一歩」ですが、ネットで調べて自分なりに咀嚼した内容が含まれるので、ツッコミ等あればお待ちしています(お手柔らかに...)。すごく遠回りに一歩一歩考察していますので、初心者でこう考える人もいるのか...ぐらいに思っていただければ。
1.経緯
前回、JavaScriptについて理解し(たような気になり)、それを踏まえてjQueryをゴリゴリ書いていくつもりでしたが、それより先にThree.jsを触りたくなってしまいました。そして、参考にしたいThree.jsのチュートリアルサイトではjQueryを使っていません。そのため、より正しくJavaScript自体を理解しなければ先に進めなくなりました。今回は、JavaScriptの中でもaddEventListenerと、DOMContentLoadedについての記事になります。
2.addEventListenerって?
巷では、こんな記述をよくみます。
document.addEventListener("DOMContentLoaded",
function(){
// 処理
}, false);
上記の記述について理解するためには、まずDOMContentLoadedを理解する必要があります。DOMContentLoadedは、簡単にいうとwindow.onloadの代わりですが、画像などの処理を待たずに実行できるため、window.onloadよりも早く処理されます。また、window.onloadのように処理が上書きされてしまうという欠点もありません。
ただ、DOMContentLoadedは独立したメソッドとして設定することはできないので、AddEventListener()メソッドを使用して、その引数としてDOMContentLoadedを設定する必要があります。
構文(※MDNより引用)は下記の通りです。
target.addEventListener(type, listener
[, useCapture, wantsUntrusted]);
この型に当てはめて考えると、先ほどの文はこうなります。
document.addEventListener('DOMContentLoaded',
function(){
// 処理
}, false);
target(対象)...document
type(対象とするイベントの種類を表す文字列)...DOMContentLoaded
listener(関数)...function(){ 処理 }
後ろの諸々[ ]...false(今回は省略します)
「DOMContentLoadedというイベントを、addEventListenerというメソッドを使って読み込みます。それが完了したら、listener部分に記載している処理を実行します。(意訳)」という感じでしょうか。
ここで一つ疑問があります。targetが「document」になっているのはどうしてでしょうか。素人考えだと、window.onloadと同じノリで、window.addEventListenerとしてくれれば似た処理として覚えやすいのですが...。と思い、調べたところ、下記のようなものがありました。
window.addEventListener('Load',
function(){
// 処理
}, false);
このパターンでは、document部分がwindowに変わっている代わりに、先ほど 'DOMContentLoaded' となっていた部分が、'Load'となっています。これは偶然でしょうか。たまたま別のターゲットに、別のイベントが設定されているとも考えられます。比較のために並べてみます。
//一つめ
document.addEventListener('DOMContentLoaded',
function(){
// 処理
}, false);
//二つめ
window.addEventListener('Load',
function(){
// 処理
}, false);
このような記述の違いが生じているのは、イベントターゲットによって受け取れるイベントが異なるためです。DOMContentLoadedというイベントはdocmentオブジェクト上にのみ存在するので、windowというターゲットには設定できないのです(参考 https://code-examples.net/ja/q/b7cc80 )。そのため、DOMContentLoadedを使うときは、必ずdocument.addEventListener...という記述とセットになっている、ということになります。なんだか釈然としなかったのですが、よく考えたらDOMはDocumentObjectModelの略なので、documentしかターゲットにならないというのも、納得...ですかね。(混乱)
3.documentとwindowの違いは?
では、そもそもオブジェクト(イベントターゲット)としてのdocumentとwindowの違いは何なのでしょうか。先ほどのふたつの記述は、ほとんど同じと思って良いものでしょうか。検索してみても、なかなかコレ!という記事に巡り会えなかったのですが、このサイトの回答が参考になりました。(参考 https://teratail.com/questions/31662 )
「windowにはwindowを操るもの、documentにはhtmlのdocument自体を操るようなものが入っている」ということです。なるほど。さらに色々調べたところ、doumentはDOMツリーを操るものであり、画像など(画像や、その他のスクリプト)はDOMツリーの守備範囲外ということがなんとなくわかってきました。だから、下記のふたつの例でいうと、documentをイベントターゲットにしている「一つめ」の方が(画像などを無視している分)読み込みが早いということになります。一方、windowをターゲットにしている「二つめ」の方は、冒頭にも出てきた、window.onloadのイメージにより近いということになります。
//一つめ
document.addEventListener('DOMContentLoaded',
function(){
// 処理
}, false);
//二つめ
window.addEventListener('Load',
function(){
// 処理
}, false);
このあたりについては、下記のサイトが簡潔でわかりやすく、参考になりました。
4.まとめ
この記事の流れ通りにまとめると、下記のような感じになります。
①画像などの読み込みを待たずに、早く処理を行いたい場合や、処理の上書きをしたくない場合、window.onloadの代わりにDOMContentLoadedを使う。
②DOMContentLoadedはAddEventListenerの引数として使用する。この場合、targetとして設定できるのはdocumentのみ。
③AddEventListenerのtargetとしてwindowを設定することもできるが、この場合はtypeをDOMContentLoadedにすることはできない。Loadなどを使う。また、この場合、DOMツリーだけを読み込むのではなく、画像などの読み込みを待ってからの処理となる。
こう見るとわかりにくいですね...。混乱した部分を一つずつ整理していったので、覚えた順番が違えばもっとスッキリ分かったのかも?と思いました。もっと簡潔にまとめるなら下記のような感じでしょうか。
①window.onloadの別の書き方として、addEventListenerというものを使うことができる。これを使用することで、「処理が上書きされてしまう」というwindow.onloadの欠点をカバーできる。
②addEventListenerにはtargetとtypeを、それぞれ設定できる。例えば、targetをwindow、typeをLoadに設定するなど。targetとtypeには相性があり、好きな組み合わせを使える訳ではない。
③targetにdocument、typeにDOMContentLoadedを設定することで、DOMツリーを読み込むという設定にできる。対象がDOMのみになるので、画像は含まれず、windowをtargetにした場合に比べ、読み込みが早くなる。
今回はaddEventListenerと、DOMContentLoadedについてでした。私はぜひThree.jsを触りたいのですが...。なかなか道のりが長そうです。頑張ります。
この記事が気に入ったらサポートをしてみませんか?