| この記事の要点 |
- Array は JavaScript の配列を扱うビルトインオブジェクト
- 生成は
[1, 2, 3] のリテラル記法、または new Array(3) / Array.of(1,2,3) / Array.from(iter) - 主要メソッド:
push / pop / shift / unshift / map / filter / reduce / forEach / find / some / every - 破壊的(元配列を変更)と非破壊的(新配列を返す)の区別は超重要。
sort / splice / reverse は破壊的 - ES2023 で非破壊版(
toSorted / toReversed / toSpliced / with)が追加された
|
Array とは
Array(配列)は、JavaScript で順序付きの値のリストを表すビルトインオブジェクトです。型は混在可能で、数値・文字列・オブジェクト・関数など何でも入ります。インデックスは 0 始まりで、length プロパティで要素数を取得できます。
配列の生成
// リテラル(最も推奨)
const a = [1, 2, 3];
const mixed = [1, 'two', { x: 3 }, [4, 5]];
const empty = [];
// コンストラクタ
const b = new Array(3); // length=3 の空配列(要素は )
const c = new Array(1, 2, 3); // [1, 2, 3]
// Array.of: 引数を要素として
const d = Array.of(3); // [3] (new Array(3) との違いに注意)
// Array.from: iterable / array-like から
const e = Array.from('abc'); // ['a', 'b', 'c']
const f = Array.from({length: 3}, (_, i) => i * 2); // [0, 2, 4]
要素の追加・削除(破壊的)
| メソッド | 位置 | 戻り値 |
push(v) | 末尾に追加 | 新しい length |
pop() | 末尾を取り出す | 取り出した要素 |
unshift(v) | 先頭に追加 | 新しい length |
shift() | 先頭を取り出す | 取り出した要素 |
splice(i, n, ...) | 任意位置の追加 / 削除 | 削除された要素配列 |
const arr = [1, 2, 3];
arr.push(4); // [1, 2, 3, 4]
arr.pop(); // [1, 2, 3] 戻り値: 4
arr.unshift(0); // [0, 1, 2, 3]
arr.shift(); // [1, 2, 3] 戻り値: 0
// splice(開始位置, 削除個数, 追加要素...)
arr.splice(1, 1, 'a', 'b'); // [1, 'a', 'b', 3]
変換系(非破壊的、新配列を返す)
map: 全要素を変換
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2); // [2, 4, 6]
const strs = nums.map(String); // ['1', '2', '3']
// インデックスも受け取れる
nums.map((v, i) => `${i}: ${v}`); // ['0: 1', '1: 2', '2: 3']
filter: 条件で抽出
const nums = [1, 2, 3, 4, 5];
const even = nums.filter(n => n % 2 === 0); // [2, 4]
const users = [
{name: 'Alice', age: 25},
{name: 'Bob', age: 17},
{name: 'Carol', age: 30}
];
const adults = users.filter(u => u.age >= 20);
// [{name:'Alice',age:25}, {name:'Carol',age:30}]
reduce: 集約
const nums = [1, 2, 3, 4];
// 合計
const sum = nums.reduce((acc, n) => acc + n, 0); // 10
// 最大値
const max = nums.reduce((a, b) => Math.max(a, b)); // 4
// グループ化
const items = [
{type: 'fruit', name: 'apple'},
{type: 'fruit', name: 'banana'},
{type: 'veg', name: 'carrot'}
];
const grouped = items.reduce((acc, item) => {
(acc[item.type] ??= []).push(item.name);
return acc;
}, {});
// { fruit: ['apple', 'banana'], veg: ['carrot'] }
検索系
| メソッド | 用途 | 戻り値 |
indexOf(v) | 値の位置 | index / -1 |
includes(v) | 含むか | true / false |
find(fn) | 最初に一致する要素 | 要素 / undefined |
findIndex(fn) | 最初に一致する位置 | index / -1 |
some(fn) | 1 つでも条件を満たすか | true / false |
every(fn) | 全て条件を満たすか | true / false |
const nums = [1, 2, 3, 4];
nums.includes(3); // true
nums.indexOf(3); // 2
nums.find(n => n > 2); // 3
nums.findIndex(n => n > 2); // 2
nums.some(n => n > 3); // true
nums.every(n => n > 0); // true
並べ替え
// sort は破壊的、デフォルトは文字列比較!
[10, 1, 2, 21].sort(); // [1, 10, 2, 21] ← 注意
[10, 1, 2, 21].sort((a,b) => a - b); // [1, 2, 10, 21]
// 降順
[1, 2, 3].sort((a, b) => b - a); // [3, 2, 1]
// オブジェクト配列
const users = [{age: 30}, {age: 20}, {age: 25}];
users.sort((a, b) => a.age - b.age);
// [{age:20}, {age:25}, {age:30}]
// 反転(破壊的)
[1, 2, 3].reverse(); // [3, 2, 1]
結合 / 平坦化
// concat: 連結(非破壊的)
[1, 2].concat([3, 4]); // [1, 2, 3, 4]
// スプレッド構文(ES6+)
[...[1, 2], ...[3, 4]]; // [1, 2, 3, 4]
// flat: ネスト配列を平坦化
[1, [2, [3, [4]]]].flat(); // [1, 2, [3, [4]]]
[1, [2, [3, [4]]]].flat(Infinity);// [1, 2, 3, 4]
// flatMap: map + flat(1)
[[1, 2], [3, 4]].flatMap(x => x); // [1, 2, 3, 4]
// join: 文字列化
[1, 2, 3].join('-'); // '1-2-3'
反復処理
const arr = ['a', 'b', 'c'];
// forEach: 関数を順に実行(戻り値なし)
arr.forEach((v, i) => console.log(i, v));
// for...of: 値を順に
for (const v of arr) {
console.log(v);
}
// for...in: index(オブジェクトの列挙にも使えてしまうので注意)
for (const i in arr) {
console.log(i, arr[i]);
}
// entries / keys / values
for (const [i, v] of arr.entries()) {
console.log(i, v);
}
ES2023 の非破壊メソッド
ES2023 で元配列を変更しない版のメソッドが追加されました。React の state のようなイミュータブル前提のコードで便利です。
| 破壊的 | 非破壊(新規) |
sort | toSorted |
reverse | toReversed |
splice | toSpliced |
arr[i] = x | with(i, x) |
const arr = [3, 1, 2];
const sorted = arr.toSorted(); // [1, 2, 3]、arr は変わらない
const arr2 = ['a', 'b', 'c'];
const replaced = arr2.with(1, 'B'); // ['a', 'B', 'c']、arr2 は変わらない
破壊的 / 非破壊的 一覧
| 破壊的 | 非破壊的 |
| push, pop, shift, unshift | map, filter, reduce, reduceRight |
| splice, sort, reverse, fill, copyWithin | slice, concat, flat, flatMap, join |
| — | find, findIndex, indexOf, includes, some, every |
| — | toSorted, toReversed, toSpliced, with(ES2023) |
コピー
const arr = [1, 2, 3];
// 浅いコピー
const a1 = [...arr];
const a2 = arr.slice();
const a3 = Array.from(arr);
// 深いコピー(要素がオブジェクトの場合)
const deep = structuredClone(arr); // モダンブラウザ
const deep2 = JSON.parse(JSON.stringify(arr)); // 簡易、関数は失う
FAQ
Q: 配列の長さは?
A: arr.length。length に小さい値を代入すると切り詰められます(arr.length = 0 で空に)。
Q: 配列か判定する方法は?
A: Array.isArray(value)。typeof は "object" としか返さないため不可。
関連
- Object — 配列以外のオブジェクト
- Map / Set — キー付きコレクション
- Iterator — for...of で回せる抽象
- スプレッド構文 — 配列の展開
- 分割代入 — 配列から変数への取り出し