jQuery は、2006 年に登場した JavaScript のライブラリーです。2010 年 1 月に公開された 1.4 など、版を重ねるごとに機能と速さが改善され、一時は多くの Web サイトで当たり前のように読み込まれていました。今では、jQuery でしていたことの多くを、ブラウザーの標準の API だけで同じくらい短く書けます。ここでは、jQuery が広く使われた理由を振り返り、よく使う書き方を標準の API に置き換える対応表を紹介します。
jQuery が広く使われた理由
大きな理由は、ブラウザーごとの違いを吸収してくれたことです。当時は、同じことをするにもブラウザーによって書き方が違いました。
- イベントの登録は、IE8 までは
attachEvent()、ほかのブラウザーはaddEventListener() - 通信に使う
XMLHttpRequestは、IE6 では ActiveX の部品として作る必要があった - CSS のセレクターで要素を探す
querySelectorAll()は、IE7 までは使えなかった
jQuery を使えば、これらの違いを気にせず、$(".item").addClass("active") のように短く書けました。条件に合う要素すべてにまとめて処理できること、メソッドを . で続けて書けること、プラグインが豊富なことも人気の理由でした。
今は、主要なブラウザーがそろって標準の API に対応しているため、違いを吸収するための層はほとんど要らなくなりました。
対応表
| やりたいこと | jQuery | 標準の API |
|---|---|---|
| 要素を 1 つ取る | $("#main") | document.querySelector("#main") |
| 要素をすべて取る | $(".item") | document.querySelectorAll(".item") |
| 中の要素を探す | $(el).find(".x") | el.querySelectorAll(".x") |
| 近い祖先を探す | $(el).closest(".card") | el.closest(".card") |
| class を付ける・外す | addClass / removeClass | el.classList.add() / remove() |
| class を切り替える | toggleClass("on") | el.classList.toggle("on") |
| class があるか調べる | hasClass("on") | el.classList.contains("on") |
| 属性を読む | attr("href") | el.getAttribute("href") |
| data 属性を読む | data("id") | el.dataset.id |
| 文字を入れる | text("…") | el.textContent = "…" |
| イベントを登録する | on("click", fn) | el.addEventListener("click", fn) |
| 要素を追加する | append(child) | el.append(child) |
| 要素を消す | remove() | el.remove() |
| スタイルを変える | css("color", "red") | el.style.color = "red" |
| 通信する | $.getJSON(url) | fetch(url) と response.json() |
| DOM の準備を待つ | $(fn) | defer 属性、DOMContentLoaded |
| オブジェクトを合成する | $.extend({}, a, b) | { ...a, ...b } |
置き換えるときに気をつけること
対応表のとおりに書き換えるだけでは、動きが変わってしまう点がいくつかあります。
すべての要素への処理は、自分でくり返す。 jQuery は、取り出したすべての要素にまとめて処理をしてくれました。querySelectorAll() が返す NodeList では、forEach() で 1 つずつ処理します。
// $(".item").addClass("active") に当たる書き方
document.querySelectorAll(".item").forEach((el) => {
el.classList.add("active");
});
見つからないときは null になる。 jQuery では、要素が無くても何も起きずに済みました。querySelector() は要素が無いと null を返すので、そのままメソッドを呼ぶとエラーになります。無いことがありうる要素は、先に確かめます。
fetch は、HTTP のエラーでは失敗にならない。 fetch() は、サーバーが 404 や 500 を返しても、通信そのものができれば成功として扱います。response.ok を確かめてから中身を読みます。
const response = await fetch("/api/items.json");
if (!response.ok) {
throw new Error("読み込みに失敗しました: " + response.status);
}
const items = await response.json();
data 属性の値は文字列のまま。 jQuery の data() は、"10" を数値に、"true" を真偽値に変えて返すことがありました。dataset は常に文字列なので、必要なら Number() などで変換します。
HTML を入れるときは注意する。 jQuery の html() に当たるのは innerHTML ですが、利用者の入力などを含む文字列を入れると、クロスサイトスクリプティング (XSS) の原因になります。文字として表示するだけなら textContent を使います。
イベントを親要素でまとめて受け取る書き方 (jQuery の $(document).on("click", ".btn", fn)) は、closest() を使えば標準の API でも書けます。詳しくは「onclick 属性をやめて、イベントを JavaScript から登録する」で紹介しています。
jQuery を使い続ける場合
すでに jQuery と多くのプラグインで作られたサイトを、すぐに書き換えるのは大変です。使い続けるなら、少なくとも、サポートされている新しい版に上げておきます。古い版には、HTML の文字列を扱う部分などに、XSS につながる脆弱性が見つかっているものがあります。
版を上げると、廃止されたメソッドが使えなくなることがあります。jQuery の公式から、古い書き方を見つけて警告を出してくれる jQuery Migrate というプラグインが出ているので、移行の作業に役立ちます。新しく作る部分から標準の API で書き、少しずつ jQuery への依存を減らしていく方法も現実的です。
まとめ
- jQuery は、ブラウザーごとの違いを吸収し、短く書けることで広く使われた
- 今は、
querySelectorAll、classList、addEventListener、fetch、closestなどの標準の API で、同じことを書ける - 置き換えでは、すべての要素へのくり返し、
nullの確認、response.okの確認を忘れない - jQuery を使い続けるなら、サポートされている新しい版に上げる