使おうとした変数や関数が見つからないときのエラーです。スペルミスと宣言忘れが主な原因です。
console.log(message);
const message = "Hello";
const message = "Hello";
console.log(message);
▶ 修正済みコードを実行エディタで開く
let・constで宣言した変数は、宣言より前で使うとReferenceErrorになります(一時的死角)。宣言してから使う順序にしましょう。名前の綴り・大文字小文字も一致させます。
混同しやすい2つですが、意味はまったく違います。ここを取り違えると直し方も変わります。
| 状態 | 意味 | 対処 |
|---|---|---|
x is not defined | その名前自体がどこにも存在しない | 宣言する/綴りを直す/読み込み順を直す |
x is undefined | 変数はあるが値が入っていない | 代入漏れ・戻り値なしの関数を疑う |
Cannot access 'x' before initialization | let/constを宣言前に使った(TDZ) | 宣言をその使用より上へ移す |
存在するかどうかだけ確かめたいときはtypeofを使います。typeofは未定義の名前に対してもエラーを出さない唯一の演算子です。
// 未定義でもエラーにならない安全なチェック
if (typeof myLib !== "undefined") {
console.log("myLibは読み込み済み");
} else {
console.log("myLibはまだ存在しません");
}
出てきた名前でほぼ原因が決まります。自分のエラーの名前を探してください。
| エラー | 原因と対処 |
|---|---|
$ is not definedjQuery is not defined | jQuery本体を読み込む前に自分のJSが動いています。jQueryの<script>を先に置くか、自分のコードをdeferにします。 |
require is not defined | ブラウザ、またはESモジュール内でCommonJSのrequire()を使っています。importに書き換えます。 |
module is not definedexports is not defined | 同じくCommonJS前提のコードをブラウザ/ESモジュールで実行しています。exportに書き換えます。 |
process is not defined | process.envはNode.jsのものです。ブラウザではビルドツール側の環境変数(Viteならimport.meta.env)を使います。 |
document is not definedwindow is not defined | Node.jsやSSR(Next.jsのサーバー側)にはDOMがありません。ブラウザでのみ動く処理はuseEffect内やtypeof window !== "undefined"のガード内に置きます。 |
fetch is not defined | 古いNode.js(v18未満)です。Nodeを上げるかnode-fetchを導入します。 |
| 自作の関数名 | 綴り・大文字小文字違い、またはファイルの読み込み漏れ。次の節を確認してください。 |
<button onclick="doSomething()">が動かない場合、関数がグローバルに存在していないのが原因です。特に多いのが次の3つです。
onclickから見えません{ }や別の関数の中で定義している<script type="module">
function hello() { alert("hi"); } // onclickからは見えない
</script>
<button onclick="hello()">押す</button>
OK
<button id="btn">押す</button>
<script type="module">
function hello() { alert("hi"); }
document.getElementById("btn").addEventListener("click", hello);
</script>
onclick属性をやめてaddEventListenerで登録するのが最も確実です。どうしてもonclickを使うならwindow.hello = hello;と明示的にグローバルへ公開します。
let・constで宣言した変数は、宣言行に到達するまで「一時的死角(TDZ)」にあり、触るとエラーになります。var・functionとの挙動の差を押さえておくと原因が読めます。
// function宣言は巻き上げられるので前に呼べる
greet();
function greet() { console.log("hello"); }
// const/letの関数式は前に呼べない(ReferenceError)
// bye();
const bye = () => console.log("bye");
bye();
function greet(){} — 定義より前でも呼べるvar x — 前でも参照できるが値はundefinedlet x / const x — 前で参照するとReferenceError(TDZ)◯◯ is not definedの◯◯)<script>の順番を入れ替える、または自分のコードにdeferを付ける下のエディタに貼り付けて実行すれば、宣言順やスコープの違いをその場で確認できます。