jQuery / メソッド / .get() - 選択した要素を配列として取得する

jQueryの.get(index)は選択集合からDOM(Document Object Model、文書オブジェクトモデル)要素を一つ取り出し、引数なしの.get()は全要素を通常のJavaScript配列として返します。どちらもjQueryオブジェクトではないため、続けて使えるメソッドが変わります。インデックスは0から始まり、負の値は末尾から数えます。

get・eq・角括弧の戻り値を区別する

.get()の二つの形式を区別すると、ネイティブDOM APIとjQueryの混同を避けられます。classListやtextContentを使うなら.get(0)で要素を取り出します。.addClass()や.text()をつなぐなら.eq(0)でjQueryオブジェクトを維持します。

式 戻り値 空の選択・範囲外
$items.get(0) 最初のDOM要素 undefined
$items[0] 最初のDOM要素 undefined
$items.get(-1) 最後のDOM要素 undefined
$items.eq(0) その要素を含むjQueryオブジェクト lengthが0のjQueryオブジェクト
$items.get() 全DOM要素の通常の配列 空配列[]

インデックスは親の中で何番目の子かではなく、現在のjQuery集合内の位置です。3要素なら0・1・2が有効で、-1は最後、-3は最初です。3と-4は範囲外になります。角括弧の[-1]には.get(-1)のように末尾から数える機能はありません。

一つの要素と配列全体を確認する

全コードをUTF-8のget-demo.htmlとして保存し、ブラウザーで開きます。コンテンツ配信ネットワーク(CDN)から公式jQueryファイル4.0.0を読み込むためインターネット接続が必要ですが、パッケージのインストールは不要です。選択・追加・空のリスト・初期化と以下の配列比較を3.7.1と4.0.0で実行しました。

.get(index)の結果にネイティブのclassList.add()を使って背景を強調します。.get()の配列にはJavaScriptのmap()で各ノードのtextContentを集めます。結果はHTMLの挿入ではなく.text()で表示します。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Read DOM elements with get</title>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <style>
    body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 24px auto; padding: 16px; }
    button, select { font: inherit; margin: 4px; }
    .picked { background: #d9f4ef; font-weight: bold; }
    pre { white-space: pre-wrap; overflow-wrap: anywhere; }
  </style>
</head>
<body>
  <h1>Read a DOM element or an array</h1>
  <label for="index">Index:</label>
  <select id="index"><option>0</option><option>1</option><option>-1</option><option>9</option></select>
  <button type="button" id="read">Read</button>
  <button type="button" id="add">Add Delta</button>
  <button type="button" id="empty">Empty list</button>
  <button type="button" id="reset">Reset</button>
  <ul id="items"><li>Alpha</li><li>Beta</li><li>Gamma</li></ul>
  <pre id="result" aria-live="polite"></pre>
  <script>
    $(function () {
      const initial = "<li>Alpha</li><li>Beta</li><li>Gamma</li>";
      function read() {
        const $items = $("#items > li");
        const index = Number($("#index").val());
        const element = $items.get(index);
        const elements = $items.get();
        $items.removeClass("picked");
        if (element !== undefined) element.classList.add("picked");
        const label = element === undefined ? "undefined" : element.textContent;
        const labels = elements.map(node => node.textContent).join(", ");
        $("#result").text(`get(${index})=${label}\narray=${labels}\ncount=${elements.length}`);
      }
      $("#read, #index").on("click change", read);
      $("#add").on("click", function () {
        if (!$("#items > li").filter(function () { return this.textContent === "Delta"; }).length) {
          $("<li>").text("Delta").appendTo("#items");
        }
        read();
      });
      $("#empty").on("click", function () { $("#items").empty(); read(); });
      $("#reset").on("click", function () {
        $("#items").html(initial);
        $("#index").val("0");
        read();
      });
      read();
    });
  </script>
</body>
</html>

初期状態ではAlphaが強調されます。

get(0)=Alpha
array=Alpha, Beta, Gamma
count=3
  1. Indexを1にすると2番目のBetaが強調されます。
  2. -1にするとGammaを選びます。
  3. そのままAdd Deltaを押すとcountが4、最後がDeltaになります。繰り返してもDeltaは重複追加されません。
  4. 9では最初の行がget(9)=undefinedとなり、強調はなくなります。配列全体と個数は引き続き表示されます。
  5. Empty listでcountが0、array=の後が空になります。-1や0を選んでもundefinedです。
  6. Resetで3項目とインデックス0に戻ります。Readは現在の条件で読み直します。

read()は毎回新しく選択するため、追加したDeltaも反映します。以前のjQuery集合や配列の要素数が、文書の変化に応じて自動増加するとは考えないようにします。

配列の変更とノードの変更は異なる

.get()は配列を作りますが、DOMノードは複製しません。開発者ツールのConsoleで次の完全な部分コードを実行します。文書に挿入しない一時要素を二つ使い、最後に整理します。

const $items = $("<li>One</li><li>Two</li>");
const elements = $items.get();
elements.reverse();
elements[0].textContent = "Changed";
console.log(`array=${elements.map(node => node.textContent).join(",")}`);
console.log(`jQuery=${$items.get().map(node => node.textContent).join(",")}`);
console.log(`same node=${elements[0] === $items.get(1)}`);
console.log(`get(9)=${typeof $items.get(9)} | eq(9).length=${$items.eq(9).length}`);
console.log(`get(-1)=${$items.get(-1).textContent} | bracket[-1]=${typeof $items[-1]}`);
$items.remove();
array=Changed,One
jQuery=One,Changed
same node=true
get(9)=undefined | eq(9).length=0
get(-1)=Changed | bracket[-1]=undefined

reverse()が変えるのは返された配列の順序だけで、元のjQuery集合はOneが先頭のままです。ただし配列の先頭は、元の集合の2番目と同じノードです。そのtextContentをChangedにすれば、元の集合から読む値も変わります。別の配列とノードの複製を区別します。全要素の配列化には.toArray()も使えます。

要素がない場合とメソッドの混同

undefinedの.classListや.textContentを読むとエラーです。例のようにundefinedを確認してからネイティブAPIを使います。.get(0).addClass()もDOM要素にjQueryメソッドを呼ぶので適切ではありません。.eq(0).addClass()で続けるか、取り出した要素を$(element)で包みます。

.get()はjQueryオブジェクトからDOM要素を取り出し、通信は行いません。HTTPリクエストを送る$.get(url)とは呼び出し先も役割も違います。結果が違う場合はセレクターの範囲、集合のlength、0からのインデックス、動的変更後の再選択を順に確認します。