今回は「配列の中にオブジェクト、そのオブジェクトの中にさらに配列」という、ネストが深い構造を対象に、ステップ実行解説を紹介します。
変数の状態を逐次追跡しながら、条件分岐やループ処理を理解できるようにします。
練習問題:配列 → オブジェクト → 配列のネスト構造
let school = [
{
className: "1年A組",
students: [
{ name: "Alice", scores: [95, 88, 92], passed: false },
{ name: "Bob", scores: [62, 70, 58], passed: false }
]
},
{
className: "1年B組",
students: [
{ name: "Charlie", scores: [78, 85, 80], passed: false },
{ name: "David", scores: [55, 60, 65], passed: false }
]
}
];
// 各生徒の平均点を計算して合格判定
for (let i = 0; i < school.length; i++) {
let classroom = school[i];
for (let j = 0; j < classroom.students.length; j++) {
let student = classroom.students[j];
let total = 0;
for (let k = 0; k < student.scores.length; k++) {
total += student.scores[k];
}
let avg = total / student.scores.length;
if (avg >= 70) {
student.passed = true;
}
}
}
console.log(school);
JavaScript出力(抜粋)
[
{
className: "1年A組",
students: [
{ name: "Alice", scores: [95, 88, 92], passed: true },
{ name: "Bob", scores: [62, 70, 58], passed: false }
]
},
{
className: "1年B組",
students: [
{ name: "Charlie", scores: [78, 85, 80], passed: true },
{ name: "David", scores: [55, 60, 65], passed: false }
]
}
]
JavaScriptステップ実行(逐次追跡)
| i | j | k | 学生 | scores | total | avg | 条件評価 | passed |
|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | Alice | [95,88,92] | 0→95 | – | – | false |
| 0 | 0 | 1 | Alice | [95,88,92] | 95→183 | – | – | false |
| 0 | 0 | 2 | Alice | [95,88,92] | 183→275 | – | – | false |
| 0 | 0 | – | Alice | [95,88,92] | 275 | 91.67 | 91.67 >= 70 → true | true |
| 0 | 1 | 0 | Bob | [62,70,58] | 0→62 | – | – | false |
| 0 | 1 | 1 | Bob | [62,70,58] | 62→132 | – | – | false |
| 0 | 1 | 2 | Bob | [62,70,58] | 132→190 | – | – | false |
| 0 | 1 | – | Bob | [62,70,58] | 190 | 63.33 | 63.33 >= 70 → false | false |
| 1 | 0 | 0 | Charlie | [78,85,80] | 0→78 | – | – | false |
| 1 | 0 | 1 | Charlie | [78,85,80] | 78→163 | – | – | false |
| 1 | 0 | 2 | Charlie | [78,85,80] | 163→243 | – | – | false |
| 1 | 0 | – | Charlie | [78,85,80] | 243 | 81 | 81 >= 70 → true | true |
| 1 | 1 | 0 | David | [55,60,65] | 0→55 | – | – | false |
| 1 | 1 | 1 | David | [55,60,65] | 55→115 | – | – | false |
| 1 | 1 | 2 | David | [55,60,65] | 115→180 | – | – | false |
| 1 | 1 | – | David | [55,60,65] | 180 | 60 | 60 >= 70 → false | false |
解説ポイント
- 三重ループの構造
- 外側
for (i)→ クラス - 中間
for (j)→ 学生 - 内側
for (k)→ 各学生のスコア
- 外側
- ネストされたオブジェクト&配列の参照
school[i].students[j].scores[k]で配列内の値を取得student.passed = trueでオブジェクトを直接更新
- 条件分岐
- 平均点
avg >= 70で合格判定
- 平均点
- 逐次表のメリット
- どの生徒のどのスコアが計算されているか、平均値がどう変化しているかを明確に追える
- 参照型の注意
student変数はオブジェクト参照なので、passed更新は元のschool配列に反映される
応用ポイント
- このパターンは「成績計算」「売上データ集計」「ネストした設定オブジェクトの更新」など、実務で非常によく出てくる
- ネストが深くなる場合は、逐次追跡表やデバッグログを作るとバグを防ぎやすい
- 条件や集計を増やす場合でも、基本のステップ実行の考え方は同じ


