8-3. 配列・オブジェクト・分割代入
このセクションで学ぶこと
Section titled “このセクションで学ぶこと”- 配列の基本操作と高階メソッド(
map・filter・reduceなど)を使いこなす - 破壊的メソッドと非破壊的メソッドの違いを理解する
- オブジェクトの作成・操作・スプレッド構文によるマージを学ぶ
- 分割代入(配列・オブジェクト・関数引数)で簡潔なコードを書けるようになる
- JSONとJavaScriptオブジェクトの変換方法を理解する
const fruits = ["apple", "banana", "cherry"];
fruits[0] // "apple"fruits.length // 3fruits[fruits.length - 1] // "cherry"(最後の要素)
// 要素の追加・削除fruits.push("date") // 末尾に追加 → ["apple", "banana", "cherry", "date"]fruits.pop() // 末尾を削除して返す → "date"fruits.unshift("avocado") // 先頭に追加fruits.shift() // 先頭を削除して返す高階メソッド(関数を受け取るメソッド)
Section titled “高階メソッド(関数を受け取るメソッド)”配列の高階メソッドは現代のJavaScriptで最も頻繁に使われる機能のひとつだ。
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// forEach:各要素に対して順番に処理を実行するnumbers.forEach(n => console.log(n * 2));// 2, 4, 6, 8, ...
// map:各要素を変換した新しい配列を返すconst doubled = numbers.map(n => n * 2);// [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
// filter:条件に合う要素だけを抽出した新しい配列を返すconst evens = numbers.filter(n => n % 2 === 0);// [2, 4, 6, 8, 10]
// find:条件に最初に合う要素を返す(なければ undefined)const firstBig = numbers.find(n => n > 5);// 6
// some:少なくとも1つ条件を満たすか(boolean)numbers.some(n => n > 9); // true
// every:全て条件を満たすか(boolean)numbers.every(n => n > 0); // true
// reduce:配列を1つの値に集約するconst sum = numbers.reduce((acc, n) => acc + n, 0);// 55(初期値0から始めて順に足していく)
// メソッドチェーン(組み合わせる)const result = numbers .filter(n => n % 2 === 0) // 偶数だけ抽出 .map(n => n * n) // 二乗する .reduce((acc, n) => acc + n, 0); // 合計// 2²+4²+6²+8²+10² = 4+16+36+64+100 = 220その他の便利メソッド
Section titled “その他の便利メソッド”const arr = [3, 1, 4, 1, 5, 9, 2, 6];
// sort:破壊的ソート(元の配列が変わる)arr.sort((a, b) => a - b); // 昇順:[1, 1, 2, 3, 4, 5, 6, 9]arr.sort((a, b) => b - a); // 降順:[9, 6, 5, 4, 3, 2, 1, 1]
// slice:部分配列を取得(元の配列は変わらない)[0, 1, 2, 3, 4].slice(1, 3) // [1, 2](index 1〜2)[0, 1, 2, 3, 4].slice(-2) // [3, 4](末尾から2つ)
// flat:ネストした配列を平坦化[1, [2, [3, [4]]]].flat() // [1, 2, [3, [4]]][1, [2, [3, [4]]]].flat(Infinity) // [1, 2, 3, 4]
// includes:要素が含まれるか[1, 2, 3].includes(2) // true
// indexOf:要素の位置(なければ -1)[1, 2, 3, 2].indexOf(2) // 1(最初のインデックス)
// join:配列を文字列に結合["a", "b", "c"].join(", ") // "a, b, c"
// スプレッド構文:配列を展開して新しい配列を作るconst a = [1, 2, 3];const b = [4, 5, 6];const merged = [...a, ...b]; // [1, 2, 3, 4, 5, 6]const copy = [...a]; // 浅いコピー注意:破壊的メソッドと非破壊的メソッド
sort、push、pop、spliceは元の配列を変更する(破壊的)map、filter、slice、concatは新しい配列を返す(非破壊的)破壊的メソッドは意図しない副作用を引き起こすことがある。配列のコピーを作ってから操作する習慣をつけよう。
オブジェクト
Section titled “オブジェクト”オブジェクトの基本
Section titled “オブジェクトの基本”const user = { name: "Alice", age: 30, email: "alice@example.com", isAdmin: false,};
// プロパティへのアクセスuser.name // "Alice"(ドット記法)user["email"] // "alice@example.com"(ブラケット記法)
// プロパティの追加・更新・削除user.role = "editor"; // 追加user.age = 31; // 更新delete user.isAdmin; // 削除
// プロパティの存在確認"name" in user // trueuser.hasOwnProperty("name") // trueプロパティの省略記法とメソッド定義
Section titled “プロパティの省略記法とメソッド定義”const name = "Bob";const age = 25;
// 変数名とプロパティ名が同じなら省略できるconst user = { name, // name: name と同じ age, // age: age と同じ greet() { // function キーワードを省略できる return `こんにちは、${this.name}!`; },};オブジェクトの操作
Section titled “オブジェクトの操作”const user = { name: "Alice", age: 30, role: "admin" };
// Object.keys:キーの配列Object.keys(user) // ["name", "age", "role"]
// Object.values:値の配列Object.values(user) // ["Alice", 30, "admin"]
// Object.entries:[キー, 値] のペア配列Object.entries(user) // [["name", "Alice"], ["age", 30], ["role", "admin"]]
// Object.assign:オブジェクトをマージ(破壊的)const base = { a: 1, b: 2 };const extra = { b: 3, c: 4 };Object.assign(base, extra); // base が { a: 1, b: 3, c: 4 } に変わる
// スプレッド構文によるマージ(非破壊的・推奨)const merged = { ...base, ...extra }; // 元のオブジェクトは変わらない
// スプレッドはプロパティの上書きにも使えるconst updated = { ...user, age: 31 }; // age だけ更新した新しいオブジェクト分割代入(Destructuring)
Section titled “分割代入(Destructuring)”分割代入を使うと、配列やオブジェクトから値を取り出して変数に代入するコードが簡潔になる。
配列の分割代入
Section titled “配列の分割代入”const [first, second, third] = [10, 20, 30];// first = 10, second = 20, third = 30
// 要素をスキップするconst [a, , c] = [1, 2, 3];// a = 1, c = 3
// 残りをまとめて取得(残余要素)const [head, ...tail] = [1, 2, 3, 4, 5];// head = 1, tail = [2, 3, 4, 5]
// デフォルト値const [x = 0, y = 0] = [10];// x = 10, y = 0
// 変数の交換(分割代入を使うとスッキリ)let p = 1, q = 2;[p, q] = [q, p];// p = 2, q = 1オブジェクトの分割代入
Section titled “オブジェクトの分割代入”const user = { name: "Alice", age: 30, role: "admin" };
const { name, age } = user;// name = "Alice", age = 30
// 別名をつけるconst { name: userName, role: userRole } = user;// userName = "Alice", userRole = "admin"
// デフォルト値const { name: n, email = "未設定" } = user;// n = "Alice", email = "未設定"(userにemailプロパティがないため)
// ネストしたオブジェクトconst config = { server: { host: "localhost", port: 3000 }, db: { host: "localhost", port: 5432 },};const { server: { host, port } } = config;// host = "localhost", port = 3000関数引数での分割代入
Section titled “関数引数での分割代入”実務で最もよく使われるパターン。引数のオブジェクトを直接分割代入して受け取れる。
// 分割代入なしの場合function createUser(options) { const name = options.name; const age = options.age; const role = options.role || "user"; // ...}
// 分割代入を使う(推奨)function createUser({ name, age, role = "user" }) { return { name, age, role };}
createUser({ name: "Alice", age: 30 });// { name: "Alice", age: 30, role: "user" }JavaScriptのオブジェクトとJSONは見た目が似ているが別物だ。APIのレスポンスはJSON文字列として受け取り、JavaScriptのオブジェクトに変換して使う。
// オブジェクト → JSON文字列const user = { name: "Alice", age: 30 };const json = JSON.stringify(user);// '{"name":"Alice","age":30}'
JSON.stringify(user, null, 2); // インデント付きで読みやすく出力// {// "name": "Alice",// "age": 30// }
// JSON文字列 → オブジェクトconst parsed = JSON.parse('{"name":"Alice","age":30}');// { name: "Alice", age: 30 }
// 注意:JSONにできないものJSON.stringify(undefined) // undefined(文字列にならない)JSON.stringify(function(){}) // undefinedJSON.stringify({ fn: function(){} }) // '{}'(関数プロパティは除外される)| 項目 | ポイント |
|---|---|
| 配列の高階メソッド | forEach・map・filter・reduce・find を使いこなす |
| 破壊的 vs 非破壊的 | sort・push は破壊的。map・filter は非破壊的 |
| オブジェクト操作 | スプレッド構文でコピー・マージするのが現代の主流 |
| 分割代入 | 配列・オブジェクトから値を取り出す際に使う |
| JSON | stringify(オブジェクト→文字列)と parse(文字列→オブジェクト) |