ReferenceError: x is not defined

宣言していない名前を読もうとしたときに出ます。綴り違い、読み込み順、スコープの外、 Node とブラウザで存在しないもの。原因を多い順に並べ、それぞれ直したコードを載せています。

実行して検証済み処理系Node 22.22.3対応ES1難易度○○○○目安8更新

どこにも宣言が無い名前を読もうとしたときに出ます。

javascript
console.log(notDeclared);
ReferenceError: notDeclared is not defined
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8

まず綴りを確かめてください。 大文字小文字も区別されます。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
undefined
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
この環境には無い

似ているエラーとの違い

ここを取り違えると、探す場所を間違えます。

文言 意味 探す場所
x is not defined 宣言が無い 綴り・読み込み・スコープ
Cannot access 'x' before initialization 宣言はある。まだ使えない 宣言の位置
Cannot read properties of undefined 変数はある。中身が undefined 値の出どころ
x is not a function 変数はある。関数ではない 呼び出し

x is not defined だけが「名前そのものが見つからない」です。

typeof なら落ちない

javascript
function setUp() {
const config = { retry: 1 };
}

setUp();

console.log(config);
ReferenceError: config is not defined
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{ retry: 1 }

typeof は、宣言が無くても例外にならない数少ない書き方です。 あるかどうかを調べたいときに使えます。

javascript
if (true) {
const inside = 1;
}

console.log(inside);
ReferenceError: inside is not defined
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
undefined undefined object

ただし let / const の宣言より前では、typeof でも落ちます。 そちらは別のエラーです。 → Cannot access before initialization

原因1: スコープの外から読んでいる

javascript
useHelper();

// helper.js は、このあとで読み込まれる
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
ReferenceError: undeclared is not defined

config は関数の中だけの名前です。外からは見えません。

外で使いたいなら、返して受け取ります

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
1 1

{} のブロックでも同じです。

letconstブロックの中だけで生きています。

原因2: 環境に無いものを使っている

同じコードでも、動く場所によって存在しないものがあります。

上はこのページの実行環境(ブラウザのワーカー)での結果です。画面を持たないので windowdocument もありません。

名前 ブラウザの画面 Node ワーカー
window document ある 無い 無い
require 無い CommonJS のときだけ 無い
process 無い ある 無い
globalThis ある ある ある

どこでも使えるのは globalThis だけです。

require is not defined が出たときは、そのファイルが モジュールとして読まれているimport を使う)ことを疑ってください。

原因3: 読み込み順

<script> を並べる書き方では、後ろのファイルの中身は前のファイルから見えません。

import で書けば、順番は処理系が解決します。 古い書き方のまま並べているなら、使う側を後ろに置いてください。

原因4: 代入したつもりで宣言していない

宣言せずに代入すると、strict モードでは代入の時点で落ちます。

strict でないと、代入は通ってしまいます。 そしてグローバルに名前が増えます。

気づかないうちにグローバルを汚しています。 import / export のあるファイルは自動的に strict なので、実務では落ちるほうが普通です。

必ず constlet を書いてください。

探しかたの順序

  1. エラーの文に出ている名前をそのまま検索する。宣言が1つも無ければ綴り違い
  2. 宣言があるなら、それが同じスコープにあるか見る
    • 関数やブロックの中なら → 返して受け取る
  3. window document require process のどれかなら → 環境の違い
  4. どれでもなければ、宣言より前で使っていないか見る
    • その場合、文言は Cannot access ... before initialization になっているはず

このページの実行結果は Node 22.22.3 のものです。文言は処理系と版によって変わります。自分の環境で出た文言で検索してください。

まとめ

  • 名前そのものが見つからないとき。まず綴りを疑う
  • typeof なら宣言が無くても落ちない。存在確認に使える
  • let / constブロックの中だけ。外からは見えない
  • window document require process環境によって無い
  • 宣言せずに代入すると、strict では落ち、そうでないと黙ってグローバルが増える

変数はあるのに中身が undefined だった、という場合はこちらです。 → Cannot read properties of undefined

この記事の根拠

  1. ResolveBinding — ECMAScript® 2026 Language Specificationtc39.es
  2. The typeof Operator — ECMAScript® 2026 Language Specificationtc39.es
  3. ReferenceError: "x" is not defined — MDNdeveloper.mozilla.org

掲載しているコード例は、公開前に読み手が押したときに動くのと同じもので実行して出力を突き合わせています。結果はリポジトリに残しています。

このページの原文(Markdown)