A3. 落とし穴カタログ

「おかしい」と思ったときに、症状から原因と直し方を引く。エラーの文面は Chrome ・ Edge ・ Node.js のもの

📅 作成: 2026-10-09 / 更新: 2026-10-10

計算と比較がおかしい

症状原因直し方章
"1" + 2 が "12" になる+ は、どちらかが文字列なら連結する外から来た値は Number() で数値にしてから計算する04
結果が NaN になるundefined や数値でない文字列を計算に使った入口で Number.isNaN を調べ、おかしければ throw する04
引数を渡し忘れても何も言われず NaN足りない引数は undefined になる既定値を書く ・ 中で確かめる06
違う値どうしが等しいと判定される== が型を変換してから比べたいつも === を使う04
0.1 + 0.2 が 0.3 にならない小数は 2 進数で近似されるお金は円単位の整数で計算する ・ 表示で toFixed03
7 / 2 が 3.5 になる数値は小数を含む 1 種類だけ整数にしたいときは Math.floor03
文字数が見た目より多いlength は UTF-16 の単位の数。絵文字は 2[...s].length03

値が無い

症状原因直し方章
TypeError: Cannot read properties of undefined (reading 'x')途中のプロパティが undefined だったどこが undefined かを調べる。無いことがあるなら ?.03
if (count) で 0 が「無い」扱いになる0 ・ "" も falsycount === undefined のように、何を調べたいかを書く04
既定値を入れたら 0 や "" が消えた|| は falsy をすべて置き換える?? を使う04
配列の範囲外を読んでもエラーにならない無い番号は undefined を返すlength で範囲を確かめる05
関数の結果が undefinedreturn を書き忘れた ・ アロー関数で { } を付けたreturn を書く ・ 式 1 つなら { } を外す06
関数そのものが表示される([Function: f])() を付けずに関数を渡した呼ぶなら f()06

名前 ・ スコープ ・ this

症状原因直し方章
ReferenceError: x is not defined名前の書き間違い ・ 大文字と小文字の違い ・ スコープの外綴りと、どの { } の中で作ったかを確かめる07
ReferenceError: Cannot access 'x' before initializationlet ・ const を、宣言の行より前で使った宣言を上に移す07
TypeError: Assignment to constant variable.const の変数に入れ直した入れ直すなら let03
関数の中の変数が、外から見えてしまうlet ・ const を付け忘れ、グローバルにできた宣言を付ける。モジュールか strict モードにすると、エラーで気づける07
this.x が undefined ・ NaNメソッドを取り出して(コールバックとして)呼んだ() => obj.m() ・ obj.m.bind(obj)07
TypeError: Cannot read properties of undefined (reading 'x')(クラスの中で)同上。クラスは strict なので this が undefined同上08
ループで作った関数が、全部同じ値を見るvar のループ変数は 1 つしかないlet にする09
ReferenceError: Must call super constructor …子クラスの constructor で super() より前に this を使った先頭で super(…) を呼ぶ08

配列とオブジェクト

症状原因直し方章
コピーを変えたら、元も変わった代入は参照を写すだけ{ ...o } ・ [...arr] でコピーする05
コピーしたのに、中の配列が元と一緒に変わる... のコピーは 1 段目だけstructuredClone(o)05
同じ中身なのに === が falseオブジェクトの === は「同じものか」を比べる中身を 1 つずつ比べる05
[10, 9, 1].sort() が [1, 10, 9]引数なしの sort は文字列として並べるsort((a, b) => a - b)05
並べ替えたら元の配列まで変わったsort は元の配列を並べ替える[...arr].sort(…)05
SyntaxError(JSON.parse で)JSON の書式が正しくない。キーが " で囲まれていない、など中身を表示して形を確かめる。try ・ catch で受ける10

非同期

症状原因直し方章
結果が出る前に次の行が動く ・ 表示の順番が違う非同期の処理を待っていないawait で待つ ・ 続きを then の中に書く11
値ではなく Promise が返ってくるasync 関数はいつも Promise を返す呼ぶ側で await する11
SyntaxError: await is only valid in async functions and the top level bodies of modulesasync の付いていない関数の中で await を使った関数に async を付ける ・ 一番外側なら .mjs にする11
Uncaught (in promise) Error: …失敗した Promise を誰も受けていないawait して try ・ catch ・ .catch(…) を付ける11
try で囲んだのにエラーが捕まらないエラーが起きたのは、try を抜けた後で動いた処理の中Promise にして await する11
タイマーが時刻どおりに呼ばれない重い処理が流れを止めている重い処理を分ける ・ 短くする11
2 つの待ちに、合計の時間がかかるawait を 1 つずつ順に書いた関係が無ければ Promise.all11

ファイルとモジュール

症状原因直し方章
ReferenceError: require is not defined in ES module scope, you can use import insteadES Modules のファイルで require を使ったimport に書き換える12
SyntaxError: Cannot use import statement outside a moduleCommonJS として読まれるファイルで import を使った拡張子を .mjs にする ・ package.json に "type": "module"12
警告 MODULE_TYPELESS_PACKAGE_JSON"type" の無い package.json の下で、.js に import を書いたpackage.json に "type": "module"12
CommonJS から名前付きで import できないNode.js が名前を見つけられない書き方だった既定の export として受けてから分ける12
あるはずのファイルが ENOENT で見つからないパスはカレントフォルダから数えられるjoin(import.meta.dirname, …) でスクリプトの場所から組み立てる12
読んだ行の末尾に見えない文字が付くWindows の改行 \r\n の \r が残ったsplit(/\r?\n/) で分ける11
import で見つからない(拡張子なし)ES Modules は拡張子を省略できない"./math.mjs" と拡張子まで書く10

画面とイベント

症状原因直し方章
HTML をダブルクリックで開くと、スクリプトが動かない。Console に … has been blocked by CORS policyfile:// で開いたページからは、type="module" のファイルを読み込めないローカルサーバを立てて http://localhost:… で開く14
TypeError: Cannot read properties of null (reading 'textContent')querySelector が要素を見つけられず null を返した。# ・ . の付け忘れ、綴りの違いセレクタを確かめる15
入力した文字の中の HTML が、そのまま動いてしまう外から来た文字を innerHTML に入れたtextContent で入れる15
親で受けたクリックの e.target が、思った要素と違うtarget は実際に押された、一番内側の要素e.target.closest("li") で目当ての要素までさかのぼる ・ 登録した要素なら e.currentTarget16
removeEventListener を呼んでも外れない登録したときと別の関数を渡した(その場で書いたアロー関数は、毎回別の関数)名前を付けた関数で登録し、同じ関数で外す16
クラスのメソッドをハンドラにしたら、this.count が読めないaddEventListener("click", this.up) と渡すと、this はボタンになる() => this.up() ・ this.up.bind(this) で渡す16
送信ボタンを押すと、ページが読み込み直されて結果が消えるフォームの送信の既定の動きsubmit イベントで e.preventDefault()17
数の欄の値を足すと、"12" のようにつながるvalue は type="number" でもいつも文字列Number(input.value) にしてから計算する17

通信と保存

症状原因直し方章
404 なのに catch に入らないfetch は 404 ・ 500 でも成功として返るres.ok を確かめて、だめなら自分で throw する18
TypeError: Failed to fetch通信そのものができなかった。ネットワークが切れている ・ CORS で止められたConsole の CORS のエラーを見る。別のオリジンなら、サーバ側で許可してもらう18
保存した回数に 1 を足すと "11" になるlocalStorage は値を文字列にして保存する読むときに Number(…)19
保存したオブジェクトを読むと "[object Object]"オブジェクトを、そのまま文字列にして保存したJSON.stringify で保存し、JSON.parse で戻す19
sessionStorage に入れた値が、別のタブで読めないsessionStorage はタブごとに分かれ、タブを閉じると消えるタブをまたぐなら localStorage19