$()の正体とは?jQueryオブジェクトが返すものを解説

$()は関数ではあるが「DOM要素」を返していない

jQueryを触り始めたとき、多くの人がこう思います。

「$('#menu')はmenu要素を取得している」

半分正しく、半分間違いです。
実際には、$()はDOM要素を返していません。

返しているのは「jQueryオブジェクト」です。

この違いを理解しないまま使うと、なぜか動かないコードや、意図しない挙動に悩まされます。
そしてここが、jQueryがただのショートカットではない理由でもあります。

$()の戻り値 ― jQueryオブジェクト

例えば次のコードです。

var el = $("#menu");

このelはHTML要素ではありません。
typeofを確認すると分かります。

console.log(typeof el);

結果は「object」です。
ではDOM要素でしょうか?

console.log(el instanceof HTMLElement);

falseになります。

つまり、$("#menu")はDOMノードではありません。
DOM要素を内部に保持したラッパーオブジェクトです。

中身は配列に近い構造

jQueryオブジェクトの内部は配列に似ています。

console.log(el[0]);

ここで初めてDOM要素が取得できます。

複数要素の場合も同じです。

var items = $(".item");
console.log(items.length);
console.log(items[1]);

これは「一致したDOM要素の集合」を1つのオブジェクトとして扱っています。

つまりjQueryの本質は
DOMコレクション操作ライブラリです。

なぜわざわざラップしているのか

理由はメソッドチェーンです。

$("#menu")
  .addClass("open")
  .css("color", "red")
  .fadeIn();

これが成立するのは、各メソッドがDOMではなく
jQueryオブジェクト自身を返しているからです。

もしgetElementByIdが返るだけなら、こうなります。

var el = document.getElementById("menu");
el.classList.add("open");
el.style.color = "red";

1つずつ操作が必要になります。

jQueryは「対象要素の集合」を保持し続けることで、連続操作を可能にしました。

$()はセレクタ関数ではない

$()は単なるセレクタ関数だと思われがちですが、それも正確ではありません。

実は$()は入力によって挙動が変わります。

入力 動作
文字列(CSSセレクタ) 要素検索
HTML文字列 要素生成
DOM要素 ラップ
関数 ready登録

例です。

$("<div>");        // 要素生成
$(document.body);  // DOMラップ
$(function(){});   // ready

つまり$は「取得関数」ではなく、
統一エントリーポイントです。

jQueryオブジェクトとDOMの違いで起きる問題

ここが重要です。
次のコードはエラーになります。

$("#menu").innerHTML = "変更";

なぜかというと、innerHTMLはDOMのプロパティであり、jQueryオブジェクトには存在しないからです。

正しくはこうです。

$("#menu").html("変更");

逆に、DOMメソッドを使いたい場合はこうします。

$("#menu")[0].innerHTML = "変更";

この違いを理解していないと
「取得できているのに操作できない」という混乱が起きます。

なぜこの設計になったのか

jQueryが作られた当時、問題はブラウザ互換性でした。

  • NodeListの扱いが違う
  • 配列メソッドが使えない
  • forEachが存在しない

そのため、DOM要素をそのまま返すとブラウザ差が露出してしまいます。
そこでjQueryはDOMをラップし、統一APIを提供しました。

つまりjQueryオブジェクトは
互換性レイヤーとして機能しています。

現在との違い

現在は次が使えます。

document.querySelectorAll(".item").forEach(el=>{
  el.classList.add("open");
});

NodeListにもforEachがあり、classListも統一されました。
jQueryの必要性は小さくなりました。

ただし、jQueryのチェーン設計は多くのライブラリに影響を与えています。
Promiseの.then()や配列メソッドの連結なども思想的に近いものです。

注意点

jQueryとDOMを混在させるとバグの原因になります。

例えばイベントです。

document.getElementById("btn").addEventListener("click", handler);
$("#btn").click(handler);

両方登録すると二重実行されます。
jQueryオブジェクトとDOMは似て非なるものです。

まとめ

$()は要素取得関数ではありません。

  • jQueryオブジェクトを生成する
  • DOM要素の集合を保持する
  • 統一APIを提供する

つまりjQueryの本質は
DOMを操作するための抽象オブジェクトです。

そして$('#id')が短く書けることよりも、
「同じコードがどのブラウザでも同じように動く」ことこそが、$()の本当の価値でした。