見出し画像

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を使う。
DOMContentLoadedAddEventListenerの引数として使用する。この場合、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を触りたいのですが...。なかなか道のりが長そうです。頑張ります。

この記事が気に入ったらサポートをしてみませんか?