この記事を書いたきっかけ
Javascript を基礎から学び直しておりました。
学習先を吟味した結果、Javascript の基礎を学ぶ先として JavaScript Primer 様の記載を読み進めておりました。
このサイトの素晴らしいところは、即座に簡単な Javascript のコードをサイト上で実行できるところです。私は記述を読みつつ実行しつつ、サイトのページを進めていきました。
その折、REPL の話題が出てきました。
不勉強な私は REPL のことがほとんどわからなかったもので、実際にブラウザの開発ツールより簡単なコードを実行しました。
この時、上記サイトの記載と異なることに気づき、なぜだろうと ChatGPT に問い合わせたところ(笑)、回答が面白いと感じたため、当記事記載に至りました。
この記事を書いた人は
- SIer社で数年働き、現在は派遣で活動しているフロントエンドエンジニアです
- 開発でつよくなりたいと思いつつ、直近の実務はテストエンジニアです
- React や typescript に特化した人材になるべく勉強中 ... _(:3」∠)
REPL とは?
chatGPT の返答より
📌 REPL(Read-Eval-Print Loop)とは?
REPL は 対話型の実行環境 のことで、プログラムのコードを入力すると、即座に評価(Eval)され、結果が出力(Print)される仕組みです。
JavaScript では ブラウザの開発者ツールのコンソール や Node.js の対話モード で REPL を利用できます。
ブラウザの開発者ツールならば、webページの検証に使用したことがあります。しかし、コンソールを利用することは稀で、network で実行されたものを確認 ...位しか思い出せません。
1. 発生した謎
教科書としている JavaScript Primer 様より *一部抜粋
同じ変数名を再定義すると、構文エラーが発生します。 そのため、同じコードを再び実行するには、ブラウザでページをリロードして変数定義をリセットしないといけませんでした。
// REPLでの動作。»はREPLの入力欄 » const count = 1; undefined » const count = 2; SyntaxError: redeclaration of const count
この問題は単独のブロック文で変数定義を囲むことで回避できます。
// REPLでの動作。»はREPLの入力欄 » { const count = 1; } undefined // ここでブロック内で定義した変数`count`は参照できなくなる » { const count = 1; } undefined // ここでブロック内で定義した変数`count`は参照できなくなる
上記を Google Chrome の開発者ツールで試しました。
結果
あれ?
SyntaxError になりません。
冒頭の「きっかけ」のところで書いた、"サイトの記載と異なること" とはこのことです。
こちらは期待通りであったものの、{} 有無で同じ挙動に見えます。
2. 【質問1】理由がわからなかったので、ChatGPT に
問い合わせてみた私です。楽させて頂いております。
私:chrome の開発者ツールで REPL を試しています。{} (ブロック)での挙動を確認しようとしています。再定義できず syntaxerror になるはずが、起こりませんでした。
問いを投げた瞬間に、「あ、この内容だと聞きたいことが聞けていないし返答も求ているものが返らないだろうな」と思いました。
ChatGPT の返答
📌 {}(ブロック)の挙動が Chrome 開発者ツールの REPL で異なる理由
Chrome の 開発者ツール(DevTools)のコンソール では、トップレベルで {} を使った場合、通常のコードブロックではなく「オブジェクトリテラル」と解釈される可能性がある ため、通常の JavaScript のスコープルールと異なる挙動をすることがあります。✅ 例:REPL で {} の挙動
🔹 通常の JavaScript(スコープの制約あり){ let a = 10; } console.log(a); // ❌ ReferenceError: a is not defined
👉 ブロック {} の中で定義した let 変数は、ブロック外からアクセスできない
🔹 Chrome DevTools のコンソール(REPL)での挙動
{ let a = 10; } console.log(a); // ✅ 10(エラーにならない)
👉 本来なら ReferenceError になるはずが、開発者ツールではエラーにならない!
🚀 なぜエラーにならないのか?
📌 Chrome DevTools ではトップレベル {} を「オブジェクトリテラル」と解釈することがある
通常の JavaScript では {} は コードブロック(Block Statement) ですが、開発者ツールではトップレベルで {} を書くと オブジェクトリテラル として解釈されることがあり、スコープの挙動が異なります。✅ 確認方法
{ let x = 1 } // スコープ内の変数がブロック外でも見える console.log(x); // ✅ 1 (本来ならエラーのはずが、REPL では表示される)
🔹 ブロックを明示的にコードブロックとして解釈させる
// 即時関数で囲むと通常のスコープルールが適用される (() => { let y = 2 })(); console.log(y); // ❌ ReferenceError: y is not defined
👉 通常の JavaScript のスコープルールが適用される
🛠 解決策
✅ 「ブロック」として動作させるために let の前に ; を入れる
開発者ツールの REPL では、トップレベル {} を オブジェクトリテラルとして解釈 してしまうことがあるため、明示的にブロックを区別する方法を使うとよいです。;{ let z = 3; } console.log(z); // ❌ ReferenceError: z is not defined
👉 ; を入れることで、{} がブロックであることを明示できる!
(※「まとめ」も記載してくれていましたが割愛)
いかがでしょうか。原文のままです。
(昨今ではAIを利用することは当たり前に行われているため真新しくはないかと存じますが不慣れなままでいる)私は2点、思いました。
1:多い
2:思ったより話の核を掴んでくれてる!
[1]はこちらの問い方が曖昧なため、さもありなん。
あと、絵文字が多くて結構ポップですよね。
3. 【質問2】聞きたいことを聞くために
私は再度質問しました。
私:では、
const str = "test";
を実行した後、再度実行した際にエラーとならない理由はなんでしょうか?
ブロックと同じような効果ですか?
ChatGPT の返答
📌 const str = "test"; を再度実行してもエラーにならない理由(Chrome DevTools の REPL の特殊な仕様)
通常の JavaScript では、同じスコープで const 変数を 再定義 すると SyntaxError になるはずです。
しかし、Chrome の開発者ツール(DevTools)ではエラーにならずに再定義できてしまう ことがあります。
~ 略 ~
💡 なぜエラーにならないのか?
🚀 Chrome DevTools の REPL は「トップレベルの変数」を毎回リセットする
🔍 Chrome DevTools の REPL では、トップレベルの const / let を特別に扱っている
通常の JavaScript とは異なり、開発者ツールのコンソールでは「1つの入力ごとに新しいスコープ」が作られるため、以前に宣言した変数がリセットされる という仕様があります。✅ REPL の「スコープリセット」の仕組み
コンソールに入力するごとに「仮想的なスクリプト」が作られる
前の変数はグローバルスコープに保持されない
そのため、const でも再宣言できる
(※具体例や「まとめ」も記載してくれていましたが割愛)
な、なんだってー Σ( ºωº )
4. 【質問3】さらに引き出す
私:なるほどです。ブラウザによっても、仕様でREPLのスコープが変わってくるのですね
もはや、そう、対話です。
先日、日本マイクロソフトのエバンジェリスト(伝道師)・西脇さんが登壇されたAIのセミナーに参加した際、まさしくAIとは会話するものであると仰っていました。きっとこれでいいのです。
ChatGPT の返答
そのとおりです!🚀 ブラウザによって REPL(開発者ツールのコンソール)のスコープの仕様が異なる ため、挙動が微妙に違うことがあります。
✅ ブラウザごとの REPL のスコープの違い
Chrome(DevTools) ✅ できる 入力ごとにスコープがリセットされる
Firefox(DevTools) ❌ できない 通常のスコープルールが適用される
Edge(DevTools) ✅ できる(Chromeと同様) 入力ごとにスコープがリセットされる
Safari(DevTools) ❌ できない 通常のスコープルールが適用される
肯定が嬉しいです笑。
~ 略 ~ (具体例)
💡 なぜ仕様が違うのか?
Chrome(V8 エンジン)や Edge では、REPL の利便性を高めるために「1回の入力 = 独立したスクリプト」として処理される。
Firefox(SpiderMonkey エンジン)や Safari(WebKit)は、通常の JavaScript に近いスコープルールを適用している。
🛠 どのブラウザでも同じスコープルールで試したいなら?
✅ 明示的にブロック {} を使う{ const c = 500; } console.log(c); // ❌ ReferenceError(通常のスコープが適用される)
~ 略 ~
✅ まとめ
🔹 Chrome / Edge(V8エンジン) → 入力ごとにスコープがリセットされ、const の再定義が可能
🔹 Firefox / Safari(SpiderMonkey / WebKit) → 通常のスコープルールが適用され、const の再定義は不可
🔹 どの環境でも統一したスコープ管理をしたいなら {} でブロックを作るのがオススメ!💡 「ブラウザごとの REPL の違い」を意識すると、より深く JavaScript を理解できる!🚀
まとめ
REPL での、参照先と実際のブラウザ挙動との差分を ChatGPT に問うた結果、ブラウザ別の挙動に踏み込むことになりました。またそれは Javascript の理解へと繋がる締めくくりとなっていたのが面白かったです。