8-2. 制御フロー・関数・スコープ
このセクションで学ぶこと
Section titled “このセクションで学ぶこと”if/else・switch・三項演算子・ループなどの制御フローを書けるようになる- 関数宣言・関数式・アロー関数の違いと使い分けを理解する
- デフォルト引数・残余引数・コールバックなど関数の応用を知る
- スコープ(グローバル・関数・ブロック)のルールを理解する
- クロージャの仕組みと実用パターンを学ぶ
if / else if / else
Section titled “if / else if / else”const score = 75;
if (score >= 90) { console.log("優");} else if (score >= 70) { console.log("良"); // ← これが実行される} else if (score >= 60) { console.log("可");} else { console.log("不可");}switch
Section titled “switch”複数の値に対して分岐するときは switch が読みやすい。break を忘れると次のケースに「フォールスルー」する点に注意。
const day = "Monday";
switch (day) { case "Saturday": case "Sunday": console.log("休日"); break; case "Monday": console.log("週明け"); // ← これが実行される break; default: console.log("平日");}if/else を1行で書きたいときに使う。ネストは避ける。
const age = 20;const label = age >= 18 ? "成人" : "未成年";// ネストは避ける(読みにくい)// const label = age >= 18 ? (age >= 65 ? "高齢者" : "成人") : "未成年";for ループ
Section titled “for ループ”// 基本的なforループfor (let i = 0; i < 5; i++) { console.log(i); // 0, 1, 2, 3, 4}
// whilelet count = 0;while (count < 3) { console.log(count); count++;}
// 配列のループは for...of が推奨(インデックスが不要な場合)const fruits = ["apple", "banana", "cherry"];for (const fruit of fruits) { console.log(fruit);}
// オブジェクトのキーをループするには for...inconst obj = { a: 1, b: 2, c: 3 };for (const key in obj) { console.log(key, obj[key]);}break と continue
Section titled “break と continue”// break:ループを抜けるfor (let i = 0; i < 10; i++) { if (i === 5) break; console.log(i); // 0〜4}
// continue:その回のループをスキップして次へfor (let i = 0; i < 5; i++) { if (i === 2) continue; console.log(i); // 0, 1, 3, 4}関数宣言と関数式
Section titled “関数宣言と関数式”// 関数宣言:ホイスティング(巻き上げ)が起きるgreet("Alice"); // エラーなし(宣言前に呼べる)
function greet(name) { return `こんにちは、${name}!`;}
// 関数式:変数に関数を代入するconst greet2 = function(name) { return `こんにちは、${name}!`;};greet2("Bob");ES6で導入された短い書き方。現代のコードではアロー関数が主流。
// 通常の関数const double = function(n) { return n * 2; };
// アロー関数const double2 = (n) => { return n * 2; };
// 引数が1つのとき括弧を省略できるconst double3 = n => { return n * 2; };
// 関数本体が return 式だけのとき { } と return を省略できるconst double4 = n => n * 2;
// 引数なしconst sayHello = () => "Hello!";
// オブジェクトを返すときは () で囲む({} がブロックと区別がつかないため)const makeUser = name => ({ name, active: true });アロー関数と通常の関数の最大の違いは
thisの扱いだ。アロー関数はthisを持たず、外のスコープのthisを引き継ぐ。DOM操作やコールバックで重要になるので、第10章のフロントエンド実装で詳しく扱う。
デフォルト引数と残余引数
Section titled “デフォルト引数と残余引数”// デフォルト引数function createUser(name, role = "user", active = true) { return { name, role, active };}createUser("Alice") // { name: "Alice", role: "user", active: true }createUser("Bob", "admin") // { name: "Bob", role: "admin", active: true }
// 残余引数(...args):可変長引数を配列で受け取るfunction sum(...numbers) { return numbers.reduce((acc, n) => acc + n, 0);}sum(1, 2, 3, 4, 5) // 15関数は「第一級オブジェクト」
Section titled “関数は「第一級オブジェクト」”JavaScriptでは関数を変数に代入したり、他の関数の引数として渡したり、戻り値として返したりできる。
// 関数を引数に渡す(コールバック)function runTwice(fn) { fn(); fn();}runTwice(() => console.log("実行!")); // "実行!" が2回出力
// 関数を返す(クロージャ)function makeCounter() { let count = 0; return function() { count++; return count; };}const counter = makeCounter();counter() // 1counter() // 2counter() // 3スコープとは「変数がどこから見えるか」のルールだ。
スコープの種類┌──────────────────────────────────────────────┐│ グローバルスコープ ││ ┌───────────────────────────────────────┐ ││ │ モジュールスコープ │ ││ │ ┌──────────────────────────────┐ │ ││ │ │ 関数スコープ │ │ ││ │ │ ┌─────────────────────┐ │ │ ││ │ │ │ ブロックスコープ({})│ │ │ ││ │ │ └─────────────────────┘ │ │ ││ │ └──────────────────────────────┘ │ ││ └───────────────────────────────────────┘ │└──────────────────────────────────────────────┘const global = "グローバル";
function outer() { const outerVar = "外";
function inner() { const innerVar = "内"; console.log(global); // OK:上のスコープの変数は見える console.log(outerVar); // OK:クロージャ console.log(innerVar); // OK:自分のスコープ }
inner(); console.log(innerVar); // エラー:内側の変数は外から見えない}let / const のブロックスコープ
Section titled “let / const のブロックスコープ”// let/const はブロック {} の中だけ有効{ let x = 10; const y = 20;}console.log(x); // エラー:x is not defined
// if/for の {} も同様if (true) { let temp = "一時変数";}console.log(temp); // エラー
// var はブロックを無視して関数スコープになる(古い挙動)if (true) { var old = "古い書き方";}console.log(old); // "古い書き方"(漏れる!)内側の関数が外側の変数を「閉じ込める」現象をクロージャと呼ぶ。モジュールパターンやカウンターの実装に使われる。
function makeMultiplier(factor) { // factor は makeMultiplier の引数だが、 // 返す関数がこれを参照し続ける return n => n * factor;}
const double = makeMultiplier(2);const triple = makeMultiplier(3);
double(5) // 10triple(5) // 15クロージャの仕組み:
makeMultiplier(2) を呼ぶ └── factor = 2 のスコープが生まれる └── n => n * factor という関数がそのスコープを「閉じ込めて」返る └── double(5) を呼ぶと factor = 2 がまだ生きている → 10| 項目 | ポイント |
|---|---|
| 制御フロー | if/else・switch・三項演算子を使い分ける |
| 関数定義 | アロー関数が主流。this の扱いに注意 |
| デフォルト引数 | 引数の省略時のデフォルト値を関数定義で指定できる |
| スコープ | let/const はブロックスコープ。内側から外側は見えるが逆は不可 |
| クロージャ | 外側スコープの変数を内側の関数が参照し続ける仕組み |