Consoleにこのエラーが出たら、JavaScriptが要素を探したけれど見つからなかったという意味です。
Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')原因はほぼ次の2つのどちらかです。
- scriptが早すぎる:HTMLの要素ができる前にJavaScriptが動いている
- 探し方がまちがっている:セレクタやidの綴りがHTMLと合っていない
どちらなのかは、1行確かめるだけで見分けられます。
エラー文の読み方
| 部分 | 意味 |
|---|---|
TypeError | 値の種類がおかしい(ここでは「要素のはずがnullだった」) |
Cannot read properties of null | null(何もない)の中身を読もうとした |
(reading 'addEventListener') | 読もうとしたのはaddEventListener |
たとえばこう書いていたとします。
const btn = document.querySelector('.menu-button');
btn.addEventListener('click', () => { /* … */ });querySelectorは、要素が見つからないときnullを返します。btnがnullなので、null.addEventListenerを呼ぶことになり、エラーになります。
どちらが原因か見分ける
エラーが出た行のすぐ前に、次の1行を足して再読み込みします。
console.log(document.querySelector('.menu-button'));次に、ページの読みこみが終わったあと、Consoleに同じ1行を直接打って試します。
| 書いた場所で | Consoleで打つと | 原因 |
|---|---|---|
null | 要素が出る | scriptが早すぎる → 原因1へ |
null | null | 探し方がまちがっている → 原因2へ |
原因1:scriptが早すぎる
ブラウザはHTMLを上から順に読みます。<head>の中でscriptを読みこむと、まだ<body>の中身ができていないうちにJavaScriptが動くので、要素が見つかりません。
<!-- ✕ bodyの中身ができる前に動く -->
<head>
<script src="script.js"></script>
</head>直し方は2通りあります。どちらか1つで大丈夫です。
deferを付ける(おすすめ)
<head>
<script src="script.js" defer></script>
</head>deferを付けると、HTMLを最後まで読み終えてからscriptが動きます。<head>にまとめて書けるので、いまはこちらが主流です。
bodyの閉じタグの直前に置く
<body>
…ページの中身…
<script src="script.js"></script>
</body>昔からある方法です。ページの中身を読んだあとにscriptが来るので、要素はもうできています。
原因2:探し方がまちがっている
Consoleで打ってもnullなら、その名前の要素がページにありません。よくあるまちがいはこのあたりです。
.と#のまちがい:class="menu-button"は'.menu-button'、id="menu-button"は'#menu-button'getElementByIdに#を付けている:getElementById('#menu')ではなくgetElementById('menu')。#が要るのはquerySelectorのときだけです- 綴りや大文字小文字のちがい:
menuButtonとmenubuttonは別の名前です - 別のページで動いている:全ページで同じ
script.jsを読みこんでいて、そのボタンがないページでエラーになっている
最後のパターンは、「要素があるときだけ動かす」ように書けば解決します。
const btn = document.querySelector('.menu-button');
if (btn) {
btn.addEventListener('click', () => { /* … */ });
}短く書くなら、?.(オプショナルチェーン)も使えます。btnがnullのときは、何もせずに通り過ぎます。
btn?.addEventListener('click', () => { /* … */ });まとめ
- このエラーは「要素が見つからず、nullに対して呼んだ」という意味
- 書いた場所では
null、Consoleでは見つかる → scriptが早すぎる。deferを付けるか</body>の直前へ - どこで打っても
null→ セレクタのまちがい。.と#、綴り、getElementByIdの#を確認 - 要素がないページもあるなら、
ifで囲むか?.で呼ぶ