- JavaScript
JavaScript Array.fromの使い方|連番とNodeList変換
Array.from とは、配列に似たもの(NodeList、文字列、Set、Map、length を持つオブジェクトなど)から、新しい本物の配列を作る静的メソッドです。 第2引数に関数を渡すと、変換と同時に各要素を加工できるので、Array.from({ length: 5 }, (_, i) => i) の1行で 0〜4 の連番も作れます。
この記事では、すべてのコードを Node.js v22.22.2 で実行し、DOM に関わる部分は Chromium 141(Playwright 1.56.0)で実行して、出力をそのまま載せています。 配列の出力は、比べやすいように JSON.stringify で1行に整形したものを基本にしています(空きスロットを見せる箇所だけ console.log の表示のままです)。連番のコピペ集、fill([]) で全要素が同じ配列を指してしまう現象の再現、2次元配列の作り方、変換できるものの早見表、スプレッド構文との違い、Array.fromAsync まで、必要な箇所から読める構成にしました。
Array.fromの早見表
| やりたいこと | 書き方 | 結果 |
|---|---|---|
| 0 からの連番 | Array.from({ length: 5 }, (_, i) => i) |
[0,1,2,3,4] |
| 1 からの連番 | Array.from({ length: 5 }, (_, i) => i + 1) |
[1,2,3,4,5] |
| 逆順の連番 | Array.from({ length: 5 }, (_, i) => 5 - i) |
[5,4,3,2,1] |
| A〜Z | Array.from({ length: 26 }, (_, i) => String.fromCharCode(65 + i)) |
["A","B",…,"Z"] |
| 2次元配列(3×3 の 0 埋め) | Array.from({ length: 3 }, () => Array(3).fill(0)) |
行ごとに別の配列 |
| NodeList を配列に | Array.from(document.querySelectorAll('.item')) |
map や filter が使える配列 |
| NodeList を変換しながら加工 | Array.from(nodeList, el => el.textContent) |
["A","B","C"] |
| 文字列を1文字ずつ | Array.from('a😀b') |
["a","😀","b"] |
| Set を配列に(重複の除去) | Array.from(new Set([1,2,2,3])) |
[1,2,3] |
| Map を配列に | Array.from(map) |
[["a",1],["b",2]] |
| arguments を配列に | Array.from(arguments) |
引数の配列 |
| 非同期の値を順に集める | await Array.fromAsync(asyncIterable) |
待ち終えた値の配列 |
構文は次の3通りです。
Array.from(items)
Array.from(items, mapFn)
Array.from(items, mapFn, thisArg)
連番の配列を作る4つの書き方を比べる
連番の作り方はいくつかあります。まず4通りを並べて実行します。
// a.mjs(Node.js v22.22.2 で実行)
console.log(Array.from({ length: 5 }, (_, i) => i));
console.log([...Array(5).keys()]);
console.log(Array(5).fill().map((_, i) => i));
const a = [];
for (let i = 0; i < 5; i++) a.push(i);
console.log(a);
実行結果です。
[0,1,2,3,4]
[0,1,2,3,4]
[0,1,2,3,4]
[0,1,2,3,4]
どれも同じ結果になります。違いは、読みやすさと、開始値や刻み幅を変えるときの書き換えやすさです。
| 書き方 | 仕組み | 向いている場面 |
|---|---|---|
Array.from({ length: n }, (_, i) => i) |
length だけを持つオブジェクトを、関数で埋めながら配列にする | 式を変えるだけで開始値・刻み幅・オブジェクト化に対応できる。迷ったらこれ |
[...Array(n).keys()] |
空の配列の添字(0〜n-1)を展開する | 0 始まりの連番だけ欲しいとき。短い |
Array(n).fill().map((_, i) => i) |
空きスロットを undefined で埋めてから map する | fill を挟む理由を知っていれば読みやすい |
for + push |
1つずつ追加する | 途中で条件分岐や break を入れたいとき |
Array(n).map だけでは連番にならない理由
fill() を挟まずに map すると、関数が一度も呼ばれません。
console.log(Array(5).map((_, i) => i));
console.log(Array.from({ length: 3 }));
console.log(Array(3));
[ <5 empty items> ]
[ undefined, undefined, undefined ]
[ <3 empty items> ]
Array(5) が作るのは、長さだけがあって中身のスロットが空いている配列です。map や forEach は空きスロットを飛ばすため、結果も空きのままになります。Array.from は空きスロットを undefined として扱い、すべての位置で関数を呼ぶので、1回で連番が作れます。{ length: 3 } のように length プロパティだけを持つオブジェクトも「配列風オブジェクト」として受け取れることが、この書き方の土台です。
100万件での速度の目安
参考として、100万件の連番を作る時間を測りました(各7回実行した中央値)。
Array.from({length:n},(_,i)=>i) 33.8 ms
[...Array(n).keys()] 47.2 ms
Array(n).fill().map((_,i)=>i) 19.3 ms
for + push 19.7 ms
for + new Array(n) 4.5 ms
これは Node.js v22.22.2 の1台の環境での値で、実行環境やエンジンの版で変わります。数千件までの連番なら、どの書き方でも体感できる差にはなりません。 数百万件を繰り返し作る処理で時間が気になったときに、あらかじめ長さを決めた for ループへ書き換える、という順番で考えると読みやすさを保てます。
連番のコピペ集:開始値・刻み幅・逆順・アルファベット・日付
開始値と刻み幅を決めて作る
console.log(Array.from({ length: 5 }, (_, i) => i + 1)); // 1 から
console.log(Array.from({ length: 5 }, (_, i) => i * 2)); // 偶数
console.log(Array.from({ length: 5 }, (_, i) => 5 - i)); // 逆順
console.log(Array.from({ length: 3 }, (_, i) => String(i + 1).padStart(3, '0'))); // ゼロ埋め
[1,2,3,4,5]
[0,2,4,6,8]
[5,4,3,2,1]
["001","002","003"]
range関数にまとめる
何度も使うなら、Python の range と同じ感覚で呼べる関数にしておくと便利です。stop は含みません。
const range = (start, stop, step = 1) =>
Array.from(
{ length: Math.max(0, Math.ceil((stop - start) / step)) },
(_, i) => start + i * step
);
console.log(range(0, 5));
console.log(range(3, 8));
console.log(range(0, 20, 5));
console.log(range(10, 0, -2));
console.log(range(5, 5));
[0,1,2,3,4]
[3,4,5,6,7]
[0,5,10,15]
[10,8,6,4,2]
[]
step に負の数を渡すと逆順になり、範囲が空なら空の配列が返ります。
小数の刻み幅は整数で作ってから割る
console.log(range(0, 1, 0.1));
console.log(Array.from({ length: 10 }, (_, i) => i / 10));
[0,0.1,0.2,0.30000000000000004,0.4,0.5,0.6000000000000001,0.7000000000000001,0.8,0.9]
[0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]
0.1 を掛け算で積み上げると、浮動小数点の誤差が表に出ます。整数の連番を作ってから割ると、きれいな値になります。
アルファベットの連番
console.log(Array.from({ length: 26 }, (_, i) => String.fromCharCode(65 + i)).join(''));
console.log(Array.from({ length: 5 }, (_, i) => String.fromCharCode(97 + i)));
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
["a","b","c","d","e"]
65 は大文字の A、97 は小文字の a の文字コードです。
連番IDを持つオブジェクトの配列
テスト用のデータや、一覧画面の仮データを作るときに使えます。
console.log(Array.from({ length: 3 }, (_, i) => ({ id: i + 1, name: `item${i + 1}` })));
[{"id":1,"name":"item1"},{"id":2,"name":"item2"},{"id":3,"name":"item3"}]
アロー関数でオブジェクトを返すときは、({ ... }) のように丸かっこで囲みます。
日付の連番
const fmt = d =>
`${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
// 2026-10-01 から5日分(月は 0 始まりなので 9 が10月)
console.log(Array.from({ length: 5 }, (_, i) => fmt(new Date(2026, 9, 1 + i))));
// 月末をまたぐ連番
console.log(Array.from({ length: 4 }, (_, i) => fmt(new Date(2026, 9, 29 + i))));
// 月の連番(年をまたぐ)
console.log(Array.from({ length: 4 }, (_, i) => {
const d = new Date(2026, 10 + i, 1);
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`;
}));
// その月の日数(2026年2月)
console.log(Array.from({ length: new Date(2026, 2, 0).getDate() }, (_, i) => i + 1).length);
["2026-10-01","2026-10-02","2026-10-03","2026-10-04","2026-10-05"]
["2026-10-29","2026-10-30","2026-10-31","2026-11-01"]
["2026-11","2026-12","2027-01","2027-02"]
28
new Date(年, 月, 日) は、日に 32 や月に 12 以上を渡しても、次の月・次の年へ自動で繰り上げてくれます。日付の足し算を自分で書かずに、添字を日の位置に足すだけで、月末や年末をまたぐ連番が作れます。new Date(2026, 2, 0) は「3月の0日目」つまり2月の末日で、その月の日数を求める定番の書き方です。
fillで全要素が同じ参照になる現象と2次元配列の作り方
new Array(n).fill([])は1つの配列を使い回す
const g = new Array(3).fill([]);
g[0].push('x');
console.log(g);
console.log(g[0] === g[1]);
[["x"],["x"],["x"]]
true
最初の要素にだけ追加したつもりが、3つすべてに 'x' が入りました。 fill は、引数として受け取った1つの値を全スロットに入れます。数値や文字列ならコピーされた値として振る舞いますが、配列やオブジェクトは「同じものを指す参照」が3か所に入るだけです。g[0] === g[1] が true であることが、その証拠です。
オブジェクトでも、2次元配列でも同じことが起こります。
const o = Array(2).fill({ n: 0 });
o[0].n = 1;
console.log(o);
const m = Array(2).fill(Array(3).fill(0));
m[0][0] = 9;
console.log(m);
[{"n":1},{"n":1}]
[[9,0,0],[9,0,0]]
Array.fromなら要素ごとに新しく作られる
Array.from の第2引数は要素ごとに毎回呼ばれる関数なので、そのたびに新しい配列やオブジェクトが作られます。
// 直した後
const g2 = Array.from({ length: 3 }, () => []);
g2[0].push('x');
console.log(g2);
console.log(g2[0] === g2[1]);
const m2 = Array.from({ length: 2 }, () => Array(3).fill(0));
m2[0][0] = 9;
console.log(m2);
[["x"],[],[]]
false
[[9,0,0],[0,0,0]]
内側の Array(3).fill(0) は、入れる値が数値なのでそのまま使えます。「fill に渡してよいのは数値・文字列・真偽値・null などの値。配列やオブジェクトを並べたいときは関数で作る」と覚えておくと判断しやすくなります。
| 書き方 | 各要素は別もの? | 実行結果(先頭行だけ変更したとき) |
|---|---|---|
Array(2).fill(Array(3).fill(0)) |
同じ配列を共有 | [[9,0,0],[9,0,0]] |
Array.from({ length: 2 }, () => Array(3).fill(0)) |
別々 | [[9,0,0],[0,0,0]] |
Array(2).fill().map(() => Array(3).fill(0)) |
別々 | [[9,0,0],[0,0,0]] |
行と列の番号を使った2次元配列
外側と内側の両方で Array.from を使うと、行番号と列番号から値を決められます。
// 通し番号の入った 2行×3列
console.log(Array.from({ length: 2 }, (_, r) => Array.from({ length: 3 }, (_, c) => r * 3 + c)));
// 3×3 の掛け算の表
console.log(Array.from({ length: 3 }, (_, r) => Array.from({ length: 3 }, (_, c) => (r + 1) * (c + 1))));
[[0,1,2],[3,4,5]]
[[1,2,3],[2,4,6],[3,6,9]]
盤面、カレンダーのマス目、表形式の初期データなどに、そのまま使える形です。
NodeList・HTMLCollectionを配列に変換する
document.querySelectorAll が返す NodeList や、getElementsByClassName が返す HTMLCollection は、見た目は配列に似ていますが配列ではありません。次の HTML を Chromium 141 で開いて確かめました。
<ul id="list">
<li class="item">A</li>
<li class="item">B</li>
<li class="item">C</li>
</ul>
const nl = document.querySelectorAll('.item'); // NodeList
const hc = document.getElementsByClassName('item'); // HTMLCollection
console.log(Object.prototype.toString.call(nl), Object.prototype.toString.call(hc));
console.log(Array.isArray(nl), Array.isArray(Array.from(nl)));
console.log(typeof nl.forEach, typeof nl.map, typeof hc.forEach, typeof hc.map);
[object NodeList] [object HTMLCollection]
false true
function undefined undefined undefined
NodeList は forEach だけ持っていて、map や filter は持っていません。HTMLCollection は forEach も持っていません。 そのまま呼ぶと次のエラーになります。
TypeError: nl.map is not a function
TypeError: hc.forEach is not a function
Array.from を通すと、配列のメソッドがすべて使えるようになります。
// 直した後
console.log(Array.from(nl, el => el.textContent));
console.log([...hc].map(el => el.textContent));
console.log(Array.from(nl).filter(el => el.textContent !== 'B').map(el => el.textContent));
["A","B","C"]
["A","B","C"]
["A","C"]
Array.from(nl, el => el.textContent) のように第2引数で加工すれば、変換と map を1回で済ませられます。
生きているコレクションは配列にしてから操作する
HTMLCollection は、DOM の変化がその場で反映される「生きている」コレクションです。要素を1つ追加したあとの length を比べます。
const arr = Array.from(hc); // この時点の3件を配列に写す
const li = document.createElement('li');
li.className = 'item';
li.textContent = 'D';
document.getElementById('list').append(li);
console.log(nl.length, hc.length, arr.length);
3 4 3
querySelectorAll の NodeList は取得した時点の3件のまま、HTMLCollection は4件に増え、配列に写したものは3件のままです。
この性質は、ループの中でクラスを外すような操作と組み合わせると、意図と違う結果になります。
// 4件すべてから item クラスを外したい
let n = 0;
for (let i = 0; i < hc.length; i++) {
hc[i].classList.remove('item');
n++;
}
console.log(n, hc.length);
2 2
4件のうち2件しか処理されず、2件が残りました。 クラスを外した瞬間にその要素がコレクションから抜け、後ろの要素が前に詰まるためです。先に配列へ写しておけば、4件すべてを処理できます。
// 直した後:先に配列へ写してから操作する
const hc2 = document.getElementsByClassName('item');
let n2 = 0;
Array.from(hc2).forEach(el => { el.classList.remove('item'); n2++; });
console.log(n2, hc2.length);
4 0
| 取得方法 | 返る型 | DOM の変化 | そのまま使えるメソッド |
|---|---|---|---|
querySelectorAll |
NodeList | 反映されない(取得時点のまま) | forEach のみ |
getElementsByClassName / getElementsByTagName |
HTMLCollection | 反映される | なし(for と添字) |
element.children |
HTMLCollection | 反映される | なし(for と添字) |
Array.from(上のいずれか) |
Array | 反映されない(写した時点のまま) | map、filter、reduce などすべて |
Map・Set・文字列・argumentsの変換早見表
Array.from が受け取れるのは、反復可能なもの(for...of で回せるもの)と、配列風オブジェクト(length と添字を持つもの)の2種類です。
console.log(Array.from(new Set([1, 2, 2, 3])));
const mp = new Map([['a', 1], ['b', 2]]);
console.log(Array.from(mp));
console.log(Array.from(mp.keys()));
console.log(Array.from(mp.values()));
console.log(Array.from(mp, ([k, v]) => `${k}=${v}`));
function f() { return Array.from(arguments); }
console.log(f(1, 'a', true));
console.log(Array.from({ 0: 'a', 1: 'b', length: 2 }));
console.log(Array.from({ 0: 'a', 2: 'c', length: 3 }));
function* gen() { yield 1; yield 2; }
console.log(Array.from(gen()));
console.log(Array.from(new Uint8Array([1, 2])));
console.log(Array.from(['a', 'b'].entries()));
[1,2,3]
[["a",1],["b",2]]
["a","b"]
[1,2]
["a=1","b=2"]
[1,"a",true]
["a","b"]
["a",null,"c"]
[1,2]
[1,2]
[[0,"a"],[1,"b"]]
(8行目の null は、JSON 形式で表示したための表記で、実際の値は undefined です。)
| 変換元 | 書き方 | 結果 |
|---|---|---|
| Set | Array.from(set) |
値の配列(重複なし) |
| Map | Array.from(map) |
[キー, 値] の配列 |
| Map のキーだけ・値だけ | Array.from(map.keys()) / Array.from(map.values()) |
キーの配列・値の配列 |
| 文字列 | Array.from('abc') |
["a","b","c"] |
| arguments | Array.from(arguments) |
引数の配列 |
| NodeList / HTMLCollection | Array.from(nodeList) |
要素の配列 |
| length を持つオブジェクト | Array.from({ 0: 'a', 1: 'b', length: 2 }) |
["a","b"] |
| ジェネレーター | Array.from(gen()) |
yield された値の配列 |
| 型付き配列 | Array.from(new Uint8Array([1, 2])) |
通常の配列 |
| 配列(コピー) | Array.from(arr) |
浅いコピー |
絵文字を含む文字列を1文字ずつに分ける
console.log(Array.from('a😀b'));
console.log('a😀b'.split(''));
console.log('😀'.length);
console.log(Array.from('𠮷野'), '𠮷野'.split(''));
["a","😀","b"]
["a","(絵文字の前半)","(絵文字の後半)","b"]
2
["𠮷","野"] ["(𠮷の前半)","(𠮷の後半)","野"]
(split の結果のうち、単独では表示できない符号は「前半」「後半」と書き換えています。)絵文字や一部の漢字は、内部では2つの符号(サロゲートペア)で1文字を表します。split('') は符号の単位で切るので、1文字が2つに分かれてしまいます。Array.from は文字(コードポイント)の単位で分けるため、絵文字も「𠮷」も1要素になります。文字数を数えるときも Array.from(str).length が使えます。
複数の絵文字を結合して1つに見せている文字は、Array.from でも部品に分かれます。
console.log(Array.from('👨👩👧'));
console.log(Array.from('👨👩👧').length, '👨👩👧'.length);
const seg = new Intl.Segmenter('ja', { granularity: 'grapheme' });
console.log([...seg.segment('👨👩👧が')].map(s => s.segment));
["👨","","👩","","👧"]
5 8
["👨👩👧","が"]
見た目どおりの1文字で分けたいときは、Intl.Segmenter を使います。
| 分け方 | 'a😀b' | '👨👩👧' | 向いている場面 |
|---|---|---|---|
str.split('') |
4要素(絵文字が2つに分かれる) | 8要素 | 英数字だけと分かっている文字列 |
Array.from(str) / [...str] |
3要素 | 5要素 | 絵文字や補助漢字を含む一般的な文字列 |
Intl.Segmenter |
3要素 | 1要素 | 見た目の文字数で数えたい入力欄など |
変換できない値を渡したとき
console.log(Array.from({ 0: 'a', 1: 'b' })); // length が無い
console.log(Array.from(5));
console.log(Array.from({ a: 1 }));
Array.from(null);
Array.from(undefined);
[]
[]
[]
TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator))
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
length が無いオブジェクトや数値は、エラーにならずに空の配列になります。 「思った配列にならない」ときは、渡した値に length があるか、反復可能かを確かめます。普通のオブジェクトを配列にしたいときは、Object.keys(obj)、Object.values(obj)、Object.entries(obj) を使います。null と undefined は TypeError になるので、値が無い可能性があるときは Array.from(value ?? []) と書いておくと落ち着いて扱えます。
length の値は整数に直して使われます。
console.log(Array.from({ length: 2.7 }, (_, i) => i));
console.log(Array.from({ length: '3' }, (_, i) => i));
console.log(Array.from({ length: -1 }));
[0,1]
[0,1,2]
[]
Array.fromとスプレッド構文の違い
[...x] も配列への変換によく使われます。違いは2点です。
console.log([...'abc']);
[...{ length: 3 }];
[...null];
["a","b","c"]
TypeError: {(intermediate value)} is not iterable
TypeError: null is not iterable
| 比べる点 | Array.from(x) |
[...x] |
|---|---|---|
| 反復可能なもの(Set、Map、文字列、NodeList) | 変換できる | 変換できる |
| length だけを持つ配列風オブジェクト | 変換できる | TypeError(反復可能ではないため) |
| 変換と同時に加工 | 第2引数で1回で済む | あとから .map() を続ける(配列が2回作られる) |
| 複数をつなげる | 1つずつ | [...a, ...b] と並べて書ける |
| 空きスロット | undefined になる | undefined になる |
| コピーの深さ | 浅いコピー | 浅いコピー |
連番や { length: n } を使う場面は Array.from、すでにある配列や Set をつなげたり写したりする場面はスプレッド構文、と使い分けると自然に書けます。
空きスロットと浅いコピーの挙動も確かめておきます。
console.log([1, , 3], Array.from([1, , 3]), [...[1, , 3]]);
const src = [{ a: 1 }];
const cp = Array.from(src);
cp[0].a = 2;
console.log(src);
[ 1, <1 empty item>, 3 ] [ 1, undefined, 3 ] [ 1, undefined, 3 ]
[{"a":2}]
コピー先のオブジェクトを書き換えると、元の配列の中身も変わりました。Array.from とスプレッド構文が作るのは、配列の入れ物だけを新しくする浅いコピーです。中のオブジェクトまで複製したいときは structuredClone(src) を使います。
第2引数と、あとからmapする書き方の違い
console.log(Array.from([1, 2, 3], x => x * 2));
console.log(Array.from([1, 2], function (x) { return x * this.k; }, { k: 10 }));
[2,4,6]
[10,20]
Array.from(x, fn) は Array.from(x).map(fn) と同じ結果になり、途中の配列を作らない分だけ無駄がありません。第3引数は、関数の中の this として使う値です(アロー関数では this が変わらないため、function で書いた関数で使います)。map と違い、第2引数の関数が受け取るのは「値」と「添字」の2つで、配列全体は渡されません。
Array.fromAsyncで非同期の値を配列にする
Array.fromAsync は、非同期の反復可能オブジェクトや Promise の並びを、順に待ちながら配列にまとめるメソッドです。戻り値は Promise なので await で受け取ります。Node.js v22.22.2 と Chromium 141 で typeof Array.fromAsync が "function" になることを確認しました。MDN の Array.fromAsync のページ(今回開いて確認)では、2024年1月から主要なブラウザーで使えるようになった機能と案内されています。
async function* ag() {
for (let i = 1; i <= 3; i++) {
await new Promise(r => setTimeout(r, 50));
yield i;
}
}
console.log(await Array.fromAsync(ag()));
console.log(await Array.fromAsync([Promise.resolve(1), 2, Promise.resolve(3)]));
console.log(await Array.fromAsync(ag(), async x => x * 10));
[1,2,3]
[1,2,3]
[10,20,30]
Array.from に Promise の配列を渡しても、Promise はそのまま要素として残ります。中身の値が欲しいときは Array.fromAsync か Promise.all を使います。
Promise.allとの違いは順番に待つこと
100ミリ秒かかる処理を3つ用意して、所要時間を比べました。
const wait = (ms, v) => new Promise(r => setTimeout(() => r(v), ms));
let t = performance.now();
await Array.fromAsync({ length: 3 }, (_, i) => wait(100, i));
console.log('fromAsync', Math.round(performance.now() - t), 'ms');
t = performance.now();
await Promise.all(Array.from({ length: 3 }, (_, i) => wait(100, i)));
console.log('Promise.all', Math.round(performance.now() - t), 'ms');
fromAsync 301 ms
Promise.all 100 ms
Array.fromAsync は1つずつ順番に待ち(約300ミリ秒)、Promise.all は同時に進めます(約100ミリ秒)。
| 比べる点 | Array.fromAsync |
Promise.all |
|---|---|---|
| 進め方 | 1つずつ順番 | 同時 |
| 非同期ジェネレーターやストリーム | そのまま受け取れる | 先に全部を取り出す必要がある |
| 向いている場面 | ページを順にたどる取得、順序や負荷を保ちたい処理 | 互いに独立した処理をまとめて速く終えたいとき |
| 途中で1つが拒否されたとき | その時点で拒否される(実行で確認) | その時点で拒否される(一般に知られた仕様。今回は未実行) |
拒否されたときは、try...catch で受け取れます。
try {
await Array.fromAsync([Promise.reject(new Error('boom'))]);
} catch (e) {
console.log('reject:', e.message);
}
reject: boom
Array.fromを使う場面の判断表
| やりたいこと | 向いている書き方 |
|---|---|
| 連番、決まった長さの初期配列を作る | Array.from({ length: n }, (_, i) => ...) |
| 同じ数値や文字列で埋める | Array(n).fill(0) |
| 配列やオブジェクトを n 個並べる | Array.from({ length: n }, () => [])(fill は使わない) |
| NodeList や HTMLCollection に map・filter を使う | Array.from(list) または Array.from(list, fn) |
| 配列や Set を写す・つなげる | [...a, ...b] |
| 文字列を文字の単位で分ける | Array.from(str)、見た目の単位なら Intl.Segmenter |
| 普通のオブジェクトを配列にする | Object.entries(obj) など |
| 非同期の値を順番に集める | await Array.fromAsync(...) |
| 非同期の処理を同時に進めて集める | await Promise.all(...) |
| 値が1つだけの配列を作る | Array.of(3) は [3]。Array(3) は長さ3の空の配列になる(実行で確認) |
よくある質問
Q. Array.from の第2引数の _ は何ですか?
A. 「使わない引数」を表すための、ただの変数名です。第2引数の関数は(値, 添字)の順に受け取りますが、{ length: 5 } から作る場合の値は常に undefined なので、慣習として _ と書いて読み飛ばし、2番目の添字 i だけを使います。
Q. Array.from でコピーした配列を変更すると、元の配列も変わりますか? A. 配列への追加や削除、要素の入れ替えは元の配列に影響しません。ただし浅いコピーなので、要素がオブジェクトの場合、そのオブジェクトのプロパティを書き換えると元の配列からも同じ変更が見えます。中身まで複製したいときは structuredClone を使います。
Q. NodeList には forEach があるのに、なぜ Array.from が必要なのですか?
A. NodeList が持っているのは forEach などの一部だけで、map・filter・reduce・some などは持っていないためです。Chromium 141 で typeof nl.map が "undefined" になることを確認しました。配列のメソッドを続けて使いたいときに Array.from で変換します。
Q. Array.from と Array.of の違いは何ですか?
A. Array.from は「配列に似たもの」を配列に変換し、Array.of は「渡した引数そのもの」を要素にした配列を作ります。Array.of(3) は [3]、Array(3) は長さ3の空の配列、Array.from({ length: 3 }) は undefined が3つ入った配列です。
まとめ
- Array.from は、反復可能なものと配列風オブジェクトを本物の配列にする。第2引数で変換と加工を同時に行える
- 連番は
Array.from({ length: n }, (_, i) => i)。式を変えれば開始値・刻み幅・逆順・アルファベット・日付に応用できる fill([])は1つの配列を全要素で共有する。配列やオブジェクトを並べるときはArray.from({ length: n }, () => [])- NodeList は map を持たず、HTMLCollection は forEach も持たない。Array.from で配列にすれば、すべてのメソッドが使える
- 生きている HTMLCollection は、配列に写してから操作すると、件数がずれない
- 絵文字を含む文字列は Array.from で文字の単位に分かれる。結合された絵文字は Intl.Segmenter
- Array.fromAsync は順番に待ち、Promise.all は同時に進める。処理の性質で選ぶ
参考・出典
- MDN Web Docs「Array.fromAsync()」(developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fromAsync)
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。