【JavaScript】Cannot read properties of null (reading ‘addEventListener’)エラーの原因と対処法|DOM読み込みタイミングを理解しよう

プログラミング

JavaScriptを学び始めたばかりの頃、突然こんなエラーメッセージに遭遇したことはありませんか?

Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')

このエラーは、JavaScript初心者が最もよく遭遇するエラーの一つです。コードは間違っていないはずなのに、なぜかエラーが出てしまう。そんな経験をした方も多いのではないでしょうか。

この記事では、このエラーがなぜ発生するのか、そしてどうすれば解決できるのかを分かりやすく解説します。さらに、エラーの背景にあるDOMの仕組みについても基礎から説明していきます。

いずる
いずる

私も初めての開発の時はよくこのエラーを出してました。

エラーの全体像

エラーメッセージの意味

まず、このエラーメッセージが何を意味しているのかを理解しましょう。

Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')

このメッセージを日本語に訳すと、「nullのプロパティを読み取ることができません(addEventListenerを読み取ろうとしています)」という意味になります。

つまり、addEventListenerというメソッドを呼び出そうとしたのですが、その対象がnull(存在しない)だったため、エラーが発生しているのです。

エラーが発生する典型的なコード例

このエラーが発生する典型的なコード例を見てみましょう。

HTML

<!DOCTYPE html>
<html>
<head>
    <title>サンプル</title>
    <script src="script.js"></script>
</head>
<body>
    <button id="myButton">クリック</button>
</body>
</html>

JavaScript (script.js)

const button = document.getElementById('myButton');
button.addEventListener('click', function() {
    console.log('クリックされました');
});

一見、何も問題がないように見えますよね。HTMLにはid="myButton"というボタンがあり、JavaScriptではそのボタンを取得して、クリックイベントを設定しようとしています。

しかし、このコードを実行すると、冒頭のエラーが発生してしまいます。なぜでしょうか?

エラーの根本原因

このエラーの根本原因は、スクリプトの読み込みタイミングにあります。

HTMLファイルは、ブラウザによって上から順番に読み込まれます。上記のコード例では、以下の順序で処理が進みます。

  1. <head>タグを読み込む
  2. <script src="script.js"></script>を発見
  3. script.jsを読み込んで実行
  4. <body>タグを読み込む
  5. <button id="myButton">を読み込む

問題は、ステップ3の時点では、まだボタン要素が存在していないということです。ブラウザがHTMLを解析してDOMツリー(後述)を構築する前に、JavaScriptが実行されてしまっているのです。

そのため、document.getElementById('myButton')は要素を見つけることができず、nullを返します。そして、nullに対してaddEventListenerを呼び出そうとするため、エラーが発生するのです。

対処法:scriptタグを</body>の直前に配置

この問題を解決する最もシンプルな方法は、scriptタグを</body>の直前に配置することです。

間違った配置例

<!DOCTYPE html>
<html>
<head>
    <title>サンプル</title>
    <script src="script.js"></script>  <!-- ここに配置すると早すぎる -->
</head>
<body>
    <button id="myButton">クリック</button>
</body>
</html>

この配置では、ボタン要素が読み込まれる前にJavaScriptが実行されてしまいます。

正しい配置例

<!DOCTYPE html>
<html>
<head>
    <title>サンプル</title>
</head>
<body>
    <button id="myButton">クリック</button>
    <script src="script.js"></script>  <!-- bodyの最後に配置 -->
</body>
</html>

この配置にすることで、以下の順序で処理が進みます。

  1. <body>タグを読み込む
  2. <button id="myButton">を読み込む
  3. ボタン要素がDOM上に存在する状態になる
  4. <script src="script.js"></script>を読み込んで実行
  5. JavaScriptがボタン要素を正しく取得できる

なぜこれで解決するのか

HTMLは上から順番に読み込まれるため、scriptタグを</body>の直前に配置することで、すべてのHTML要素が読み込まれた後にJavaScriptが実行されるようになります。

これにより、document.getElementById('myButton')が呼ばれる時点では、すでにボタン要素がDOM上に存在しているため、正しく要素を取得でき、エラーが発生しなくなります。

この方法は非常にシンプルで、多くのWebサイトで採用されている標準的なアプローチです。特別な理由がない限り、scriptタグは</body>の直前に配置することをおすすめします。

DOMとは?基礎知識を解説

ここまでの説明で「DOM」という言葉が何度か出てきました。エラーの根本的な理解のために、DOMについて基礎知識を解説します。

DOMの定義

DOM(Document Object Model)とは、HTMLをJavaScriptから操作するための仕組みです。

ブラウザは、HTMLファイルを読み込むと、その内容を「ツリー構造」として解釈します。この構造のことをDOMツリーと呼びます。例えば、以下のようなHTMLがあるとします。

<html>
  <body>
    <h1>タイトル</h1>
    <p>本文</p>
  </body>
</html>

これは、ブラウザ内部では以下のようなツリー構造として表現されます。

html
 └─ body
     ├─ h1 (タイトル)
     └─ p (本文)

JavaScriptは、このDOMツリーを通じてHTML要素にアクセスし、操作することができます。document.getElementById()addEventListener()などのメソッドは、すべてこのDOMを操作するためのものです。

DOMツリーの構築プロセス

ブラウザがHTMLファイルを読み込んでから、実際にページが表示されるまでには、以下のようなプロセスがあります。

  1. パース(解析):ブラウザがHTMLファイルを読み込み、内容を解析します
  2. DOMツリー構築:解析した内容をもとに、DOMツリーを構築します
  3. レンダリング:DOMツリーとCSSを組み合わせて、画面に表示します

重要なのは、DOMツリーが構築される前にJavaScriptが実行されると、要素にアクセスできないということです。

これが、今回のエラーの根本原因です。scriptタグを<head>に配置すると、DOMツリーの構築が完了する前にJavaScriptが実行されてしまいます。その結果、document.getElementById()で要素を取得しようとしても、まだツリー上に存在しないため、nullが返されるのです。

逆に、scriptタグを</body>の直前に配置すれば、すべてのHTML要素が読み込まれ、DOMツリーが構築された後にJavaScriptが実行されます。そのため、すべての要素に正しくアクセスできるようになるのです。

このように、JavaScriptの実行タイミングは非常に重要です。DOMの仕組みを理解することで、なぜエラーが発生するのか、そしてなぜその対処法が有効なのかが、より深く理解できるようになります。

まとめ

Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')というエラーは、JavaScript初心者が頻繁に遭遇するエラーです。しかし、原因を理解すれば、簡単に解決できます。

エラーの原因は、DOMツリーが構築される前にJavaScriptが実行されていることです。HTML要素がまだ読み込まれていない状態で、その要素にアクセスしようとするため、nullが返され、エラーが発生します。

対処法は非常にシンプルで、scriptタグを</body>の直前に配置するだけです。これにより、すべてのHTML要素が読み込まれた後にJavaScriptが実行されるようになり、エラーが解消されます。

また、このエラーを通じて、DOMの仕組みやブラウザがHTMLを処理する流れを理解することも重要です。DOMとは、HTMLをJavaScriptから操作するための仕組みであり、ブラウザはHTMLを解析してDOMツリーを構築します。JavaScriptの実行タイミングがこのプロセスのどこで行われるかを意識することで、同じようなエラーに悩まされることがなくなります。

プログラミングでは、エラーに遭遇することは避けられません。しかし、エラーの原因を理解し、対処法を身につけることで、確実にスキルアップしていくことができます。この知識を活かして、より快適なJavaScript開発を楽しんでください。


※この記事は基本的な対処法を解説しています。より高度な手法についてはJavaScriptの公式ドキュメントを参照してください。

関連記事:JavaScriptでカレンダーを実装する – Dateオブジェクトの基礎から学ぶ
     JavaScriptでTODO機能を実装する – LocalStorageでデータを保存する方法

コメント

タイトルとURLをコピーしました