



WithCodeMedia-1-pc
WithCodeMedia-2-pc
WithCodeMedia-3-pc
WithCodeMedia-4-pc




WithCodeMedia-1-sp
WithCodeMedia-2-sp
WithCodeMedia-3-sp
WithCodeMedia-4-sp









生徒JavaScriptを書いたのに全然動かなくて…何から確認すればいいですか?
ペン博士まずはブラウザのコンソールでエラーを読むのが第一歩だよ。読み込み順・タイポ・要素取得のタイミングなど、原因はだいたいパターンが決まってる。今日は順番に潰していこう。
JavaScriptを書いたのに何も動かない——この状況はWeb制作の現場で誰もが経験する壁です。HTMLとCSSなら見た目ですぐ気づけますが、JavaScriptのエラーはブラウザ上では何も表示されないことが多く、どこが悪いのか見当もつかないという状況に陥りがちです。
実はJavaScriptが動かない原因の9割は、読み込み順の問題・タイポ(スペルミス)・DOM操作のタイミング・変数のスコープのどれかです。本記事ではブラウザの開発者ツールの使い方から、よくあるエラーの読み方と修正コード、デバッグの体系的な手順まで詳しく解説します。

JavaScriptのデバッグはブラウザの開発者ツール(DevTools)のコンソールパネルから始まります。コンソールを開くショートカットを覚えることが最初のステップです。
| OS・ブラウザ | ショートカット |
|---|---|
| Windows(Chrome/Edge/Firefox) | F12 または Ctrl + Shift + I |
| Mac(Chrome/Edge) | Command + Option + I |
| Mac(Safari) | Command + Option + C(要:開発メニュー有効化) |
| 右クリックメニューから | 右クリック→「検証」または「要素を調査」 |
DevToolsが開いたら「Console」タブをクリックします。赤字でエラーが表示されていれば、それがJavaScriptが動かない直接原因です。何もエラーが表示されていない場合は、後述する手順でエラーの発生場所を特定します。
コンソールのエラーメッセージは「エラーの種類:説明 at ファイル名:行番号」という形式で表示されます。例えば以下のような表示です。
<!-- コンソールに表示されるエラーの例 -->
Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
at main.js:15:23
Uncaught ReferenceError: myFunction is not defined
at index.html:28:5
Uncaught SyntaxError: Unexpected token '}'
at main.js:42
エラー名・説明・ファイル名・行番号の4点を確認し、行番号のリンクをクリックするとSources(またはDebugger)タブで該当コードに直接ジャンプできます。

JavaScriptが動かない最も多い原因の一つが、scriptタグの位置です。HTMLはDOMを上から順に構築するため、`<head>`内でJavaScriptを読み込んで`document.getElementById`などを実行すると、HTML要素がまだ存在しない状態でDOM操作しようとしてnullエラーが発生します。
<!-- NG: headタグ内でDOMを参照しようとしている -->
<head>
<script src="main.js"></script>
<!-- main.jsの中でdocument.getElementById('btn')をしてもnullになる -->
</head>
<body>
<button id="btn">クリック</button>
</body>
<!-- OK案1: bodyの閉じタグ直前に置く -->
<body>
<button id="btn">クリック</button>
<script src="main.js"></script>
</body>
<!-- OK案2: defer属性を使ってheadに書く(推奨) -->
<head>
<script src="main.js" defer></script>
</head>
<body>
<button id="btn">クリック</button>
</body>
defer属性を付けると、スクリプトはHTMLのパースを妨げずにバックグラウンドでダウンロードされ、DOMの構築が完了してから実行されます。現代のベストプラクティスはheadに`defer`で書くことです。`async`属性もありますが、こちらはDOMの完成を待たずに実行されるため、DOM操作を含むスクリプトには使えません。
既存のコードを変更したくない場合や、inline scriptの場合は`DOMContentLoaded`イベントでDOM構築後に処理を実行します。
<head>
<script>
// DOMContentLoadedでDOM構築後に実行
document.addEventListener('DOMContentLoaded', function() {
var btn = document.getElementById('btn');
if (btn) {
btn.addEventListener('click', function() {
console.log('クリックされました');
});
}
});
</script>
</head>
<body>
<button id="btn">クリック</button>
</body>
scriptタグのsrc属性のパスが間違っていると、JavaScriptファイル自体が読み込まれません。この場合コンソールに赤いエラーは出ないか、「Failed to load resource」という404エラーが出ます。
<!-- よくあるパスミスの例 -->
<!-- NG: jsフォルダにあるのにパスが違う -->
<script src="main.js"></script>
<!-- OK: 正しいパスを指定 -->
<script src="js/main.js"></script>
<!-- NG: 絶対パスと相対パスを混同 -->
<script src="/js/main.js"></script>
<!-- (ローカル環境でドキュメントルートが違うと読み込まれない) -->
<!-- 確認方法:Networkタブでステータスコードを確認 -->
<!-- 404が表示されていればパスが間違い -->
NetworkタブでJSファイルを確認するには、DevToolsを開いてNetworkタブをクリック → ページをリロード → リストの中からJSファイルを探してStatusが200(成功)か404(Not Found)かを確認します。404の場合はパスを修正してください。
JavaScriptは大文字・小文字を区別する言語です。`getElementById`を`getElementbyId`と書いたり、変数名を`userName`と`username`で揺らがしたりするだけで動かなくなります。
<script>
// NG例:タイポのパターン
// 1. メソッド名の大文字ミス
document.getElementbyId('btn'); // NG: byがByであるべき
document.getElementById('btn'); // OK
// 2. イベント名の誤り
btn.addEventlistener('click', fn); // NG: listenerのlが小文字
btn.addEventListener('click', fn); // OK
// 3. 変数名の揺らぎ
var userName = 'Taro';
console.log(username); // NG: nameが小文字 → ReferenceError
// 4. セミコロン・括弧の対応ミス(SyntaxError)
function greet() {
console.log('hello')
// 閉じ括弧が足りない → SyntaxError
</script>
コンソールに`ReferenceError: xxx is not defined`が出た場合は、変数名・関数名のスペルを確認してください。`SyntaxError`の場合は、コードの構文(括弧・クォート・セミコロン)の対応ミスを疑います。

JavaScriptが動かない原因で特に多いのが`Cannot read properties of null`エラーです。`document.getElementById`や`querySelector`でHTML要素を取得しようとしたが、IDやセレクタが一致する要素が見つからず`null`が返り、その`null`に対してメソッドを呼び出したことで発生します。
<!-- NG: HTMLにid="submiy-btn"(スペルミス)があるのに -->
<!-- JS側はid="submit-btn"を探している -->
<button id="submiy-btn">送信</button>
<script>
// getElementById('submit-btn')はnullを返す
var btn = document.getElementById('submit-btn');
btn.addEventListener('click', function() { // TypeErrorが発生
console.log('送信');
});
</script>
<!-- OK: nullチェックを入れる -->
<script>
var btn = document.getElementById('submit-btn');
if (btn) {
btn.addEventListener('click', function() {
console.log('送信');
});
} else {
console.warn('submit-btn が見つかりません');
}
</script>
<!-- オプショナルチェーン(?.)を使う方法(ES2020+) -->
<script>
document.getElementById('submit-btn')
?.addEventListener('click', function() {
console.log('送信');
});
</script>
変数がどこで定義されているかによって参照できる範囲(スコープ)が異なります。関数の外で使おうとした変数が関数の中でしか宣言されていない場合、`ReferenceError`が発生します。
<script>
// NG: 関数内で宣言した変数を外から参照しようとしている
function fetchData() {
var result = 'データ取得完了';
}
fetchData();
console.log(result); // ReferenceError: result is not defined
// OK1: 関数の外で宣言しておく
var result;
function fetchData() {
result = 'データ取得完了';
}
fetchData();
console.log(result); // 'データ取得完了'
// OK2: 戻り値として受け取る
function fetchData() {
return 'データ取得完了';
}
var result = fetchData();
console.log(result); // 'データ取得完了'
// letとconstのブロックスコープも注意
{
let blockVar = 'ブロック内のみ';
const blockConst = '定数';
}
console.log(blockVar); // ReferenceError
</script>
fetchやsetTimeoutなど非同期処理の結果を同期的に使おうとするコードは、値が取得される前に次の処理が実行されてしまいundefinedになることがあります。
<script>
// NG: fetchの結果を同期的に取得しようとしている
var data;
fetch('https://api.example.com/data')
.then(function(res) { return res.json(); })
.then(function(json) { data = json; });
console.log(data); // undefined(fetchがまだ完了していない)
// OK1: thenチェーンの中で処理する
fetch('https://api.example.com/data')
.then(function(res) { return res.json(); })
.then(function(json) {
console.log(json); // ここで処理する
updateUI(json);
})
.catch(function(err) {
console.error('取得エラー:', err);
});
// OK2: async/awaitを使う(読みやすい)
async function loadData() {
try {
var res = await fetch('https://api.example.com/data');
if (!res.ok) {
throw new Error('HTTPエラー: ' + res.status);
}
var json = await res.json();
console.log(json);
updateUI(json);
} catch (err) {
console.error('取得エラー:', err);
}
}
loadData();
</script>
コードを修正したのに古い動作のままという場合、ブラウザがキャッシュした古いJSファイルを読み込んでいる可能性があります。ハードリフレッシュでキャッシュを無視して再読み込みします。
| OS | ハードリフレッシュ |
|---|---|
| Windows Chrome/Edge | Ctrl + Shift + R |
| Mac Chrome/Edge | Command + Shift + R |
| Windows Firefox | Ctrl + F5 |
| Mac Safari | Command + Option + R |
開発中はDevToolsを開いた状態でNetworkタブの「キャッシュを無効化」(Disable cache)にチェックを入れておくと、常に最新のファイルを読み込めます。本番環境ではJSファイルのURLにバージョンクエリを付けることでキャッシュを破棄できます。
<!-- クエリパラメータでキャッシュバスティング -->
<script src="main.js?v=20260728"></script>
<!-- デプロイごとにバージョンを変えると古いキャッシュが使われなくなる -->
<script src="main.js?v=20260729"></script>

JavaScriptが動かないときに効率よく原因を特定するための手順を紹介します。
まず開発者ツールのConsoleタブを開き、赤字のエラーがないか確認します。エラーが表示されていれば、エラー名と行番号から原因を特定します。エラーがなく動かない場合はStep2に進みます。
`console.log`は最も基本的なデバッグ手段です。処理の各ポイントで変数の値を出力し、期待通りの値が入っているか確認します。
<script>
function processData(input) {
console.log('1. input:', input); // 引数を確認
var trimmed = input.trim();
console.log('2. trimmed:', trimmed);
if (trimmed === '') {
console.log('3. 空の入力 → 処理中断');
return;
}
var result = trimmed.toUpperCase();
console.log('4. result:', result);
return result;
}
var btn = document.getElementById('btn');
console.log('btn要素:', btn); // null確認
btn?.addEventListener('click', function() {
var input = document.getElementById('input-field')?.value;
console.log('input-field値:', input);
var output = processData(input);
console.log('最終出力:', output);
});
</script>
コードの特定の場所で実行を一時停止して、その時点の変数の状態を確認できます。`debugger`と書くだけで、DevToolsが開いている状態でその行で実行が止まります。
<script>
function calculateTotal(items) {
debugger; // ここで実行が一時停止する(DevToolsが開いている場合)
var total = 0;
for (var i = 0; i < items.length; i++) {
debugger; // ループ内でも確認できる
total += items[i].price;
}
return total;
}
// DevToolsのSourcesタブでステップ実行して変数を確認する
calculateTotal([
{ name: '商品A', price: 1000 },
{ name: '商品B', price: 2500 }
]);
</script>
外部APIやファイルの読み込みに問題がある場合はNetworkタブを使います。ページをリロードしてNetworkタブを開き、各リクエストのStatusとResponseを確認します。
よく遭遇するエラーメッセージとその解決策を一覧にまとめます。
| エラーメッセージ | 原因 | 対処法 |
|---|---|---|
| Uncaught TypeError: Cannot read properties of null | nullに対してメソッド呼び出し | nullチェック、IDのスペル確認、scriptタグの位置確認 |
| Uncaught ReferenceError: xxx is not defined | 未定義変数・関数の参照 | スペル確認、スコープ確認、読み込み順確認 |
| Uncaught SyntaxError: Unexpected token | 構文エラー(括弧・クォートの対応ミス) | エラー行番号のコードを確認、IDEの補完を活用 |
| Failed to load resource: net::ERR_FILE_NOT_FOUND | ファイルが見つからない | srcのパスを修正、ファイル名を確認 |
| Access to fetch blocked by CORS policy | クロスオリジンリクエストがブロック | サーバー側でCORSヘッダーを設定、プロキシを使う |
<script>
// === よくあるエラーと修正例 ===
// 1. TypeError修正例
// NG
var el = document.getElementById('missing'); // null
el.classList.add('active'); // TypeError
// OK
var el = document.getElementById('missing');
if (el) el.classList.add('active');
// 2. ReferenceError修正例
// NG(countが定義されていないブロックの外で参照)
function counter() {
let count = 0;
count++;
}
console.log(count); // ReferenceError
// OK
let count = 0;
function counter() {
count++;
}
counter();
console.log(count); // 1
// 3. SyntaxError修正例
// NG(クォートが閉じていない)
var name = 'Taro; // SyntaxError
var title = "Hello World'; // SyntaxError(クォートの種類が違う)
// OK
var name = 'Taro';
var title = "Hello World";
</script>
JavaScriptが動かないときは、まずコンソールでエラーを確認するのが鉄則です。よくある原因は①scriptの読み込み位置やdefer②DOM取得のタイミング(DOMContentLoaded)③変数名・関数名のタイポ④パスやライブラリの読み込み失敗、の4つ。エラーメッセージの読み方を身につければ、原因の切り分けが一気に速くなります。
エラーが出ていない場合、考えられる原因は①JSファイルが読み込まれていない(Networkタブで404を確認)、②イベントリスナーのトリガーが発火していない(対象要素のセレクタが間違っているなど)、③処理は実行されているが期待した動作になっていないの3パターンです。まずNetworkタブでJSファイルが200で読み込まれているか確認し、次にconsole.logをコード先頭に入れてファイル自体が実行されているかを確認してください。
WordPressでは`jQuery`がよく使われますが、`$`が競合している可能性があります。WordPressの`wp_enqueue_script`でjQueryを読み込んだ場合、`$`の代わりに`jQuery`または`(function($) { … })(jQuery);`という即時関数パターンで囲むと解決します。また、WordPress管理画面のDOMと干渉する場合はコンソールエラーを必ず確認してください。
どちらもHTMLのパースをブロックせずにJSをダウンロードします。`async`はダウンロード完了次第すぐに実行(DOMの完成を待たない)、`defer`はDOMの構築が完了してから実行される点が違います。DOM操作をするスクリプトには`defer`を使ってください。`async`はGoogleタグマネージャーやアナリティクスなど、DOMに依存しない独立したスクリプトに向いています。
ローカルでは動かない場合、CORSポリシーが原因のことが多いです。`file://`プロトコルではfetchやXMLHttpRequestがブロックされます。PHPの組み込みサーバー(`php -S localhost:8080`)やLive Serverなどのローカルサーバーを使って`http://`経由でアクセスしてください。逆に本番で動かない場合は、ファイルのパス差異・サーバーのContent-Typeヘッダー設定・HTTPSとHTTPの混在(Mixed Content)が原因であることが多いです。
まず「ESLint」でコードの文法エラーをリアルタイムに検出することを強くおすすめします。次に「JavaScript (ES6) code snippets」で補完を強化、「Debugger for Chrome」(現在はJavaScript Debugger)でVSCode内から直接ブレークポイントを設定できます。またPrettierを導入してフォーマットを統一すると、タイポや括弧ミスを早期に発見しやすくなります。
CSSの実装テクニックを「レイアウト・装飾・アニメーション・基礎・トラブル解決」の目的別に探せる総まとめページを用意しています。実装で迷ったときの索引としてどうぞ。

目的に合わせて選べる「AI副業」「AI転職」「AI活用」の3コースを用意。副収入・キャリアチェンジ・日常の生産性アップまで、あなたのゴールに合わせてAIを学べます。
会員登録はカンタン30秒で完了します。まずは公式LINEから、無料でAI学習をスタートしましょう!
WithCodeでWeb制作を習得後、フリーランスエンジニアとして活動。HTML/CSS・JavaScript・WordPress案件を中心に年間20件以上の制作実績を持つ。「難しい技術をわかりやすく」をモットーに、初心者〜中級者向けの技術記事を執筆。副業・フリーランス独立を目指す方に向けた情報発信に注力している。
公式サイト より
今すぐ
無料カウンセリング
を予約!