はじめに
プログラミングを習い始めたころ、こんな経験はありませんか。
- 教科書のコードを写して動かしたら、答えは合っている。でも、なぜその答えになるのかを説明できない
- 再帰関数の説明を聞いて「わかった気」になったのに、自分で書こうとすると手が止まる
-
console.logをあちこちに入れて、値を追いかけているうちに何を調べていたのか忘れる
プログラムの「動き」は目に見えません。コードは静止したテキストですが、実行するとそこから時間とともに変化する状態が生まれます。つまずきの多くは、この見えない動きを頭の中で正しく思い描けないことから来ています。
この連載では、JavaScript のコードを 1 ステップずつ実行しながら、その動きを 12 種類の見せ方(ビュー) で可視化する Web アプリ JSVisualizer を紹介します。
https://tntetsu.github.io/JSVisualizer/
ブラウザで開くだけで使えます。インストールもアカウント登録も要りません。
この第 0 回では、ツールの全体像と、よく知られた可視化ツール Python Tutor との違いを説明します。第 1 回からは、アルゴリズムを 1 つずつ取り上げて、それに一番合うビューで動きを見ていきます。
JSVisualizer の画面
画面は左右 2 つに分かれています。
-
左: ソースコード。自分で書いたコードを貼り付けて実行できます。いま実行している行が青く、いま計算している式がオレンジで示されます。関数の中を実行しているときは、その関数を呼び出した式(上の画像では
fact(n - 1))に紫の破線が付きます -
右: ビュー。タブを切り替えると、同じ実行の同じ瞬間を別の角度から見られます。上の画像は「コールスタック」ビューで、
fact(4)→fact(3)→fact(2)と関数の呼び出しが積み重なっている様子です
使い方は、コードを書いて「▶ 実行」を押し、上部のボタンで 1 ステップずつ進める(または戻る)だけです。スライダーで好きな時点に飛ぶこともできます。
ボタンの意味や各ビューの見方は、使い方(マニュアル)にまとめてあります。画面右上の「?」ボタンからも開けます。
特徴 1: 4 段階の細かさでステップ実行できる
「1 ステップ」の大きさを 4 段階から選べます。それぞれ「進む」「戻る」のボタンがあります。
| ボタン | 単位 | こんなときに |
|---|---|---|
| ◀式 / 式▶ | 式(最も細かい) |
a + b * c のような式が、どの順に計算されるかを見たい |
| ◀◀文 / 文▶▶ | 文 | 1 行ずつ実行の流れを追いたい |
| ◁人 / 人▷ | 人にやさしい単位 | 代入・条件判定・ループの更新など、意味のある変化だけを追いたい(入門者にはまずこれがおすすめ) |
| ⏪関数 / 関数⏩ | 関数呼び出し | 関数の中身は飛ばして、呼び出しと戻りだけを追いたい |
最初は「人」で全体の流れをつかみ、気になる箇所で「式」に切り替えて細かく見る、という使い方ができます。どの単位でも後ろに戻れるので、「あれ、今の何だっけ?」と思ったらすぐに巻き戻せます。
特徴 2: 12 種類のビュー
ビューは「何を見せるか」で大きく 3 つに分かれます。
| 分類 | 見せるもの | ビュー |
|---|---|---|
| 状態 | ある瞬間に何が記憶されているか | 変数、実行トレース、コールスタック、ライフタイム、メモリ |
| 振る舞い | 実行が時間とともにどう進むか | 式評価、置換、制御フロー、ヒートマップ、呼び出しツリー |
| データ構造 | 配列やオブジェクトの中身 | 配列、オブジェクト |
さらに、ビューには「今この瞬間だけを表示して、ステップごとに書き換わる」タイプ(例: 変数、コールスタック)と、「実行全体を一覧で見せて、今の位置だけが動く」タイプ(例: 実行トレース、置換、ヒートマップ)があります。前者は「いまどうなっているか」、後者は「全体がどう流れたか」を見るのに向いています。
たとえば次の画像は「置換」ビューです(関数の呼び出しを、その関数が返す式に置き換えていく見方なので、この名前です)。再帰関数 fact(4) が 4 * fact(3) → 4 * 3 * fact(2) → … と、数式を書き換えるように展開されていく様子が 1 枚に残ります。
同じ fact(4) でも、コールスタックビューで見ると「関数の呼び出しが積み重なる」様子が、置換ビューで見ると「式が置き換わっていく」様子が見えます。1 つの見方でピンと来なくても、別の見方ならわかることがある — これが 12 種類のビューを用意している理由です。
Python Tutor との違い
プログラムの可視化ツールとしては、Python Tutor が世界中で広く使われています。名前に反して Python だけでなく、Java・C・C++・JavaScript にも対応しています。JSVisualizer を紹介すると「Python Tutor と何が違うの?」とよく聞かれるので、ここで整理しておきます。
| JSVisualizer | Python Tutor | |
|---|---|---|
| 対応言語 | JavaScript のみ | Python・Java・C・C++・JavaScript |
| ステップの単位 | 4 段階(式・文・人にやさしい単位・関数)× 進む/戻る | 1 段階(行単位)× 進む/戻る |
| 見せ方 | 12 種類のビューをタブで切り替え | 1 種類(フレームとオブジェクトの図) |
| 今どの式を計算しているか | 式の範囲をハイライト | 行を矢印で指す |
| 再帰の全体像(呼び出しの木・置き換えによる展開) | 呼び出しツリー・置換ビューで見られる | JavaScript では、終わった呼び出しのフレームは消える |
| 実行の様子を他人と共有 | コードへのリンクは作れる(?code= 指定。後述) |
実行の様子をそのまま共有できるリンクや埋め込みコードを作れる |
Python Tutor の図(左に関数のフレーム、右にオブジェクト、参照を矢印で結ぶ)は、変数とメモリの関係を理解するうえでとてもよくできた表現です。JSVisualizer にも同じ種類の「メモリ」ビューがあります。
JSVisualizer が違うのは、その 1 つの図だけでなく、目的に合わせて見せ方を選べる点です。
- ループで変数がどう変わるかを追いたい → 変数ビュー・実行トレース
- 複雑な条件式がどう
true/falseになるかを見たい → 式評価ビュー(式の単位でステップ実行) -
ifのどちらの分岐を通ったかを見たい → 制御フロービュー - 再帰で同じ計算を何度も呼んでいないか確かめたい → 呼び出しツリー
どちらを使えばいい?
正直に言うと、どちらが優れているかではなく、向いている場面が違います。
Python Tutor が向いている場面
- Python や C など、JavaScript 以外の言語を学んでいる
- 変数・参照・メモリの関係(いわゆる「箱と矢印」)をじっくり理解したい
- 特定の実行の様子をリンク 1 つで学生に配りたい
JSVisualizer が向いている場面
- JavaScript を学んでいる・教えている
- 「式がどう計算されるか」「どの行が何回実行されたか」「再帰がどう広がるか」など、メモリの図だけでは見えにくい動きを見たい
- 同じプログラムを複数の角度から見比べて理解を深めたい
教える人へ: 特定のコードを開くリンクを作れる
JSVisualizer は URL にパラメータを付けると、決まったコードを読み込んだ状態で開けます。
https://tntetsu.github.io/JSVisualizer/?code=<コードの JSON の URL>&view=<最初に表示するビュー>
-
code:{ "title": "...", "code": "..." }という形の JSON を置いた URL -
view: 最初に「▶ 実行」を押したときに開くビュー(trace・subst・controlflowなど)
授業の資料や課題に「このリンクを開いて、実行して、ステップを進めてみよう」と書いておけば、学生はコードを写す手間なしに同じ画面から始められます。この連載でも、各回の最後にこの形式のリンクを付けます。
自分で試してみよう
この回で使った階乗のコードを開くリンクです。「▶ 実行」を押すと置換ビューが開きます。「人▷」で 1 ステップずつ進めたり、タブを切り替えたりしてみてください。
function fact(n) {
if (n <= 1) {
return 1;
}
return n * fact(n - 1);
}
console.log(fact(4));
もちろん、トップページを開いて自分のコードを貼り付けても動きます。右上の「EN」ボタンで英語表示にも切り替えられます。
まとめと次回予告
- JSVisualizer は、JavaScript のコードを 1 ステップずつ実行しながら、12 種類のビューで動きを見られる Web アプリ
- ステップの細かさを 4 段階から選べ、どの段階でも後ろに戻れる
- Python Tutor が得意な「メモリの図」に加えて、式の計算順・分岐・実行回数・再帰の広がりなど、目的に合わせた見せ方を選べる
次回(第 1 回)は、プログラミングの最初の山場である for ループ を取り上げます。「1 から 5 までの合計」を求めるコードで、変数 sum と i がどう変わっていくのかを、変数ビューで 1 ステップずつ追いかけます。

