実践JavaScript:外のデータでアプリを動かす

このコースで育てるもの

このレッスンで分かること

  • 入門で書いた script.jsapp.js として開き直し、外のデータで動くポートフォリオアプリまで育てます
  • このコースで足すのは配列のパイプライン、関数の設計、クラス、例外、正規表現、非同期処理と fetch です
  • 最初の一歩は作品データの形をそろえ、表示とデータの境目を引き直すことです

このコースで育てるもの とは

入門で完成したプロフィールサイトを土台に、外部の API からデータを取って表示するポートフォリオアプリまで育てるコースです。何を足すのか、どの順で進むのかを見取り図として先に押さえます。

入門の終わりと、このコースの始まり

入門の最後に完成した script.js は 300 行ほどありました。作品カードを組み立てる createWorkCard、配列から一覧を描き直す renderWorks、ボタンとフォームのイベント、時計、ひとことメモ。ひとつひとつの処理は短いのですが、上から順に足していった結果、ファイルの中で「どこがデータで、どこが表示か」の境目が薄れかけています。

このコースでは、そのファイルを app.js という名前で開き直します。名前を変える理由は 2 つあります。1 つは入門の成果物をそのまま残したうえで次の版を作れること。もう 1 つは、これから足していくものが「画面を動かすスクリプト」から「データを扱うアプリケーション」へ性質を変えるためです。

いまの app.js の入口はこうなっています。

// 入門の終わり。配列は手で書いてあり、書き換えると表示が変わる const works = [ { title: "プロフィールサイト", year: 2026, views: 120, published: true } ]; renderWorks(works);

このコースの終わりには、同じ場所がこうなります。

// 実践の終わり。データは外から来て、遅れて届き、ときどき失敗する async function start() { showLoading(); try { const works = await loadWorks(); renderWorks(works); } catch (error) { showError(error.message); } }

たった数行の違いに見えますが、この形を書けるようになるまでに必要な知識が、このコースの中身のほぼすべてです。await を書くには Promise が要り、catch を書くには例外の設計が要り、loadWorks を関数として切り出すには純粋関数の考えかたが要ります。

題材を入門から変えないのは手抜きではありません。新しい題材にすると、非同期処理を説明する前にその題材の説明から始めることになります。すでに手になじんだ画面を使えば、1 行目から本題に入れます。

足していくものは 6 つ

章ごとに何を足すのか、そして「いま何に困っているのか」を並べます。困りごとのほうが主役です。道具から入ると、使い道の分からない構文を覚えるだけになります。

足す道具いま困っていること
第2章map / filter / reduce / sort絞り込むたびに空の配列と for 文を書いている
第3章クロージャ / 関数を返す関数 / 純粋関数設定値がグローバルの let に散らばっている
第4章引数の分割代入 / スプレッド / entries引数が増えるたびに並び順を覚え直している
第5章クラスと継承作品はただのオブジェクトで、ふるまいを持てない
第6章と第7章例外の設計 / 正規表現失敗が握りつぶされ、入力検証が length 頼み
第8章と第9章Promise / async await / fetchデータを自分の手で書き写している

入門の pickWorks を思い出してください。空の配列を用意し、for-of でまわし、条件に合わないものを continue で飛ばし、残りを push していました。あれは正しいコードです。ただ、条件が「公開ずみ」「人気だけ」「カテゴリ別」「新しい順」と増えるにつれて、同じ形の関数が増えていきます。第2章で扱う filtersort は、その増えかたを止めるための道具です。

第10章のモジュールだけは事情が違います。このコースの実行環境では importexport を動かせないため、読んで分かるところまでを範囲とします。できないことをできると書かないために、先に断っておきます。

レッスンの 3 つの型

このコースのレッスンは 3 つの型でできています。入門と同じ作りなので、進めかたに戸惑うことはないはずです。

やること主な章
読み物手を動かさずに考えかたを押さえる第1章、第8章、第10章
関数を書く関数を 1 本書き、戻り値がテストされる第2章から第7章
画面を作るHTML と CSS と JS を書き、出来上がった画面が判定される第6章、第8章、第9章

関数を書く型では、採点は必ず 戻り値 を見ます。console.log で正しい値を出しても、return を書き忘れていれば不正解です。画面を作る型では逆に、戻り値ではなく最終的な画面の状態を見ます。「作品カードが 3 枚ある」「エラー文が表示されている」といった条件が並び、それを満たせば合格です。

各章の最後にはまとめクイズがあります。用語を答えさせる問題は出しません。すべてコードを読ませて、その結果を答えさせる形にしてあります。読めないコードは書けないからです。

分からない行が出てきたら、その場でブラウザの開発者ツールのコンソールに貼り付けて動かしてみてください。入門から変わらず、これがいちばん速い確かめかたです。

修了したときにできること

このコースを終えた時点で、ポートフォリオアプリは次の 5 つを備えています。どれも「あとで勉強すれば足せる機能」ではなく、章を進めるたびに順番に足していくものです。

  1. 作品データを外部の API から読み込む。手で書いた配列はコードから消えます
  2. 読み込んでいる間は「読み込み中」と画面に出し、届いたら一覧に差し替える
  3. 通信が失敗したときは、コンソールではなく画面に理由を出す
  4. カテゴリでの絞り込みと、表示回数や年での並び替えができる
  5. 問い合わせフォームの入力を正規表現で検証し、通らなければその場で指摘する

3 番目を軽く見ないでください。入門までのコードは、うまくいく道すじだけを書いてきました。実際のアプリケーションで手数がかかるのは、うまくいかなかったときに何を出すかのほうです。ネットワークは遅れますし、サーバーは 500 を返しますし、利用者は空欄のまま送信ボタンを押します。第6章と第9章はそこに正面から時間を使います。

逆に、このコースで扱わないと決めたものもあります。DOM の新しい API は足しません。入門で覚えた querySelector textContent classList createElement の 4 つで最後まで足ります。npm とビルドツール、TypeScript、localStorage も範囲外です。道具を増やすより、いま持っている道具で「失敗するデータ」を扱いきることを優先します。

先に決めておく約束ごと

このコースを通して使う名前と形を、ここで固定します。章をまたいで同じデータを扱うので、途中で形が変わらないようにするためです。

作品 1 件は次の 7 つの項目を持ちます。入門では 4 つでしたので、idtagscategory の 3 つが増えます。

const work = { id: 1, title: "プロフィールサイト", year: 2026, views: 120, published: true, tags: ["HTML", "CSS"], category: "site" };

id は作品を 1 件だけ探すときの目印です。第9章で API から 1 件取ってくるときに効いてきます。tags は表示用の短い文字列の配列で、category は分類用の値です。category に入れてよい値は sitecardtable の 3 つに固定します。値を絞っておくと、第2章の分類も第9章の絞り込みも同じ 3 つで通せます。

作品は入門と同じ 5 件を使います。プロフィールサイト 自己紹介カード スキル一覧の表 作品ギャラリー 学習ログ です。クラスを作る第5章では WorkWorkCollection という名前を使います。関数名と変数名は英語の camelCase で書きます。

よくある間違い

  • 入門のファイルを直接書き換えてしまう — 途中で分からなくなったときに戻る先が無くなります。script.js はそのまま残し、コピーを app.js として作ってください
// 誤り。入門の script.js を開いて上書きしていく // 正しい。script.js をコピーして app.js を作り、HTML の読み込み先を変える // <script src="app.js" defer></script>
  • データと表示を同じ関数に混ぜる — 下のように配列の宣言と描画が同じ関数に入っていると、データを外から取ってくる形に変えるときに関数ごと書き直しになります。次のレッスンからの主題がここです
// 誤り。データの出どころと描画が 1 つの関数に入っている function renderWorks() { const works = [{ title: "プロフィールサイト", views: 120 }]; // ここで描画している } // 正しい。works は引数として受け取る function renderWorks(works) { // ここは描画だけを担当する }
  • 先に第8章から手を付ける — 非同期処理はこのコースの目玉ですが、trycatch を知らないまま await のエラー処理に入ると、例外の話をしているのか非同期の話をしているのか切り分けられなくなります。第6章を先に置いてあるのはそのためです
生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部