1. ホーム
  2. JavaScript

【JavaScript】Array.from の使い方|配列風オブジェクト・反復可能オブジェクトを配列に変換する

Share

document.querySelectorAll() で取得した要素の集まりに map() を使おうとしてエラーになった、という経験はないでしょうか。これは取得したものが「配列のように見えて配列ではない」ために起こります。こうした配列風のオブジェクトを本物の配列に変換するのが Array.from() です。この記事では Array.from() の基本の使い方、第2引数のマッピング関数、文字列や Set からの変換、連番配列の作り方までを、実際のコードとともに解説します。

Array.from が必要になる場面

JavaScript には、配列のように要素が並んでいるのに Array ではないオブジェクトがいくつもあります。代表的なのが querySelectorAll() が返す NodeList や、関数内で使える arguments、文字列などです。これらは length を持ち添字でアクセスできる一方で、map()filter() といった配列のメソッドは持っていません。

Array.from() は、こうした「配列風オブジェクト(array-like)」や「反復可能オブジェクト(iterable)」を受け取り、その要素を並べた新しい配列を作って返します。一度本物の配列にしてしまえば、配列のメソッドが自由に使えるようになります。

基本の使い方

Array.from() の第1引数に、変換したいオブジェクトを渡します。次の例は、文字列を1文字ずつの配列に変換するものです。文字列は反復可能オブジェクトなので、そのまま渡せます。

main.js
const chars = Array.from("hello");
console.log(chars); // ["h", "e", "l", "l", "o"]

DOM 操作でよく使うのが、NodeList の変換です。querySelectorAll() の戻り値はそのままでは map() が使えませんが、Array.from() を通せば配列になります。

main.js
// NodeList(配列ではない)を取得
const nodeList = document.querySelectorAll(".item");

// 配列に変換すると map などが使える
const texts = Array.from(nodeList).map((el) => el.textContent);
console.log(texts);

第2引数のマッピング関数で変換と同時に加工する

Array.from() は第2引数に関数(マッピング関数)を渡せます。すると、各要素にその関数を適用しながら配列を作ります。Array.from(obj).map(fn) と同じ結果になりますが、中間の配列を作らずに済むぶん簡潔に書けます。引数として渡せるものは次のとおりです。

引数意味
第1引数変換元の配列風オブジェクト/反復可能オブジェクト(必須)
第2引数各要素を加工するマッピング関数 (element, index) => ...(省略可)
main.js
// 各要素を2倍しながら配列化する
const doubled = Array.from([1, 2, 3], (n) => n * 2);
console.log(doubled); // [2, 4, 6]

// 第2引数の関数は index も受け取れる
const labeled = Array.from(["a", "b"], (v, i) => `${i}:${v}`);
console.log(labeled); // ["0:a", "1:b"]

length を持つオブジェクトから連番配列を作る

Array.from() は、length プロパティだけを持つオブジェクトも受け取れます。{ length: 5 } のようなオブジェクトを渡すと、要素数 5 の配列ができます。中身は undefined になりますが、第2引数のマッピング関数と組み合わせると、連番の配列を手軽に作れます。

main.js
// 0 から 4 までの連番を作る
const nums = Array.from({ length: 5 }, (_, i) => i);
console.log(nums); // [0, 1, 2, 3, 4]

// 1 から 5 までにしたいときは i + 1
const oneToFive = Array.from({ length: 5 }, (_, i) => i + 1);
console.log(oneToFive); // [1, 2, 3, 4, 5]

第1引数で使わない要素は、慣習として _(アンダースコア)という名前で受け取ることが多いです。これは「この引数は使いません」という意思表示で、第2引数の index だけを使いたいときに役立ちます。

Set や Map の重複排除・変換に使う

Set も反復可能オブジェクトなので、Array.from() で配列に戻せます。配列をいったん Set に通してから Array.from() で戻すと、重複を取り除いた配列が得られます。

main.js
const arr = [1, 2, 2, 3, 3, 3];

// Set で重複を除き、Array.from で配列に戻す
const unique = Array.from(new Set(arr));
console.log(unique); // [1, 2, 3]

スプレッド構文との違い

配列風のものを配列にする方法として、スプレッド構文([...obj])もよく使われます。反復可能オブジェクトであれば、どちらでもほぼ同じ結果になります。たとえば NodeListSet[...nodeList] でも配列にできます。

違いが出るのは2点です。1つは、{ length: 3 } のような「反復できないが length は持つ」配列風オブジェクトです。これはスプレッド構文では展開できず、Array.from() でしか変換できません。もう1つは、変換と同時に加工したい場合です。Array.from() は第2引数でマッピングできますが、スプレッド構文には加工の機能がないため [...obj].map(fn) のように後から map() を付ける必要があります。length だけのオブジェクトを扱うときや、変換しながら加工したいときは Array.from() を選ぶ、と覚えておくとよいでしょう。

思った配列にならないとき

すべて undefined の配列になる

Array.from({ length: 3 }) の結果が [undefined, undefined, undefined] になるのは正しい動作です。length だけのオブジェクトには実際の要素が無いためで、中身を入れたいときは第2引数のマッピング関数で値を生成します。Array.from({ length: 3 }, () => 0) とすれば [0, 0, 0] になります。

オブジェクトを渡したのに空配列になる

{ a: 1, b: 2 } のような通常のオブジェクトを Array.from() に渡すと、空の配列が返ります。これは、対象が反復可能でも配列風(length を持つ)でもないためです。オブジェクトのキーや値を配列にしたいときは、Object.keys()Object.values()Object.entries() を使います。Array.from() はあくまで「配列風・反復可能なもの」を対象にするプロパティだと理解しておきましょう。

まとめ

Array.from() は、配列風オブジェクトや反復可能オブジェクトを本物の配列に変換するメソッドです。要点を振り返ります。

  • 第1引数に変換元(NodeList・文字列・Setlength を持つオブジェクトなど)を渡す
  • 第2引数のマッピング関数 (element, index) => ... で変換と同時に加工できる
  • Array.from({ length: n }, (_, i) => i) で連番配列を手軽に作れる
  • Set と組み合わせると重複を除いた配列が得られる
  • 反復できない通常のオブジェクトは対象外(Object.keys() などを使う)

まずは「querySelectorAll() の結果に map() を使いたい」という場面で Array.from() を思い出せると、DOM 操作がぐっと書きやすくなります。

参考ページ