【翻訳まとめ】jQuery 3.0 アップグレードガイド

  • 567
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

はじめに

jQuery 3.0が正式リリースとなったので、最新のアップグレードガイドをまとめようと思います。

原文から一部わかりやすいように言い換えたり、補足したり、省略したりしています。

注意:
長いです。主要な変更点は前回の記事【翻訳まとめ】jQuery 3.0 alpha リリースノートを参照してください。

jQuery Core 3.0 Upgrade Guide

全体像

APIを綺麗にしてバグを修正しました。
- 一部破壊的な変更があり
- 既に非推奨と公表していたAPIを削除
- ドキュメントにない隠しAPIの削除
- 特定の入力値に対する既存APIの振る舞いを修正

サポートブラウザ

  • IE9 以上
  • Chrome, Edge, Firefox, Safariの最新版とそのひとつ前のバージョン
  • Operaの最新版
  • iOS 7 以上のモバイルSafari
  • Android 4.0以上

移行プラグイン

古いコードを移行できるように新しい移行プラグインを作りました。これを用いると影響のあるコードを教えてくれるので、利用することをオススメします。
まだ1.x系または2.x系の最新版でない場合は、2段階でアップグレードする必要があります。

  • 1.11.x以下、2.1.x以下の場合
    • まず1.12.x, 2.2.xにアップグレードする
    • 1.x 移行プラグインを利用しワーニングを修正
    • 1.x 移行プラグインを削除し以下に進む
  • 1.12.x, 2.2.xの場合
    • 3.0にアップグレードする
    • 3.0 移行プラグインを利用してワーニングを修正する
    • 3.0 移行プラグインを削除

2つの移行プラグインを同時に利用することは出来ません。
また移行プラグインは基本的に圧縮されていないものを利用しましょう。

重要な変更点まとめ

変更の種類
- 破壊的変更 :warning: : 既存コードに影響をあたえる可能性があります。API仕様が変更されています。
- 新機能 :new: : 既存のコードへの影響は殆どありません。機能の追加です。
- 非推奨 :no_entry_sign: : まだjQuery 3.0には存在しますが非推奨となるAPIです。将来のバージョンで削除される可能性があります。

Ajaxについて

:warning: $.ajax()から特殊Deferred関数を削除

$.ajax()の返り値であるjqXHRオブジェクトはjQuery Deferredですが、この返り値が持つsuccess, error, complete関数が削除されました。
代わりにdone, fail, alwaysを使ってください。またPromises/A+規格準拠のthencatchも使えるようになりました。
注意: $.ajax()の引数にcallbackを指定できる同名のオプションは引き続き利用でき、非推奨にもなりません。

:warning: クロスドメインのscript取得は明示的に宣言する

$.ajax()$.get()での他のドメインからscriptを取得する場合は、dataType: "script"を指定することが必須になりました。

:warning: $.ajax()がURLのハッシュを保持するように

$.ajax()のURLにハッシュが含まれている場合、これを保持したまま送信します。

:new: $.get(), $.post()の新しい形式

$.ajax()と同様に$.get(), $.post()でも引数にObjectを指定できるようになりました。形式は$.ajax()と同じです。

HTML属性について

:warning: .removeAttr()がfalseを設定しなくなった

今まではBoolean属性(checked, selected, readonlyなど)に.removeAttr()を利用すると属性を消さずにfalseを指定していました。これは古いIEの互換のためです。
3.0ではBoolean属性でも消すようになりました。
ただ、本来はBoolean属性を切り替える場合は.prop("checked", false)を利用するべきです。

:warning: multipleのselectタグで無選択の場合、空arrayを返す

<select multiple>タグを.val()で取得する時に無選択だとnullを返していましたが、3.0から[]を返すようになりました。

:new: SVGでのクラス操作の追加

SVGはjQueryで完全にサポートされておらず、3.0でも不完全なままですが、.addClass().hasClass()などのクラス操作がサポートされました。

:no_entry_sign: 引数なしやBooleanの.toggleClass()が非推奨

.toggleClass().toggleClass(false)などは非推奨になりました。
クラス名を引数に指定してください。

コールバックについて

:new: コールバックのlockが将来の実行にのみ適応

Callbackオブジェクトのlock()関数は、すでにfireされている実行中の処理を止めず、lock()が呼ばれた後にfireされたものだけを止めるようになります。
実行中の処理も止めたい場合はstopOnFalseオプションを利用してください。

コアの処理について

:warning: jQuery 3.0はstrict modeで動作

サポート対象ブラウザはほぼ"use strict"に対応しているので、jQueryは"use strict"ありでビルドされます。あなたのコードをstrict modeで動作させる必要はありません。
かつてASP.NET 4.0はarguments.caller.calleeを利用していたので、もしASP.NETがいまだにarguments.caller.calleeを利用してたとしたらjQuery 3.0を利用することは出来ません。

:warning: document-readyが常に非同期に

document-ready処理が追加された時点で既にreadyでも同期的に処理を行わず、あくまで非同期で処理を行うようになります。
jQuery 3.0はPromises/A+標準に従うようにしているからです。
documentがreadyかどうかにかかわらず、処理の順序の一貫性を保証できます。

例:

$(function(){
   console.log("2");
});
console.log("1");
ready前に呼ばれる ready後に呼ばれる
以前 1 -> 2 の順 2 -> 1 の順
3.0 1 -> 2 の順 1 -> 2 の順

3.0以前はready後に呼ばれた場合、同期的に処理をします。

:warning: $.isNumeric()の動作変更

$.isNumeric()は数値と有限の数値に変換できるstringだけに利用されます。今までは独自にtoString()関数を足されたオブジェクトにも利用できていましたが、利用できなくなります。

:warning: 非推奨の.context.selectorを削除

jQuery 1.9ですでに非推奨になっていたものを削除。

:warning: ドキュメントにない内部関数の隠蔽

ドキュメントには記載のない内部関数が外からも利用できていましたが、これらをprivateにしました。

  • $.swap
  • $.buildFragment
  • $.domManip

:warning: 空jQueryコレクションの関数返り値がundefinedに

$("no-exist")のような空のjQueryコレクションに対して、.width()などの関数を呼んだ場合、nullではなくundefinedを返すようになりました。

  • .width()
  • .height()
  • .innerWidth()
  • .innerHeight()
  • .outerWitdh()
  • .outerHeight()
  • .offsetTop()
  • .offsetLeft()

:new: jQueryコレクションにfor...ofループを使えるように

ES2015で導入されたfor...ofループがjQueryコレクションに使えるようになりました。

var elems = $(".someclass");

for (let elem of elems) {
  // elemを操作
}

:new: $.readyが正式なPromiseとしてサポート

$.readyはthenableとしてjQuery 1.8から導入されていましたが、今後は$.whenや素のJavaScriptのPromise.resolve()にて利用できるようになりました。

$.when(
  $.ready,
  $.getScript("optional.js")
).then(function() {
   // documentがreadyでかつoptional.jsが読み込まれたら
});

:no_entry_sign: $.unique()$.uniqueSort()にリネーム

関数の動作は変更ありませんがより分かりやすいように名前が変更になりました。

:no_entry_sign: $.parseJSON()の非推奨

3.0のサポートブラウザは全てJSON.parse()をサポートしているのでこの関数は非推奨になりました。

:no_entry_sign: $(function)以外のdocument-readyの非推奨

document-readyを行う方法はいくつかあります。

$(fn);
$().ready(fn);
$(document).ready(fn);
$("selector").ready(fn);

jQuery 3.0では1つ目を推奨し、他の方法は非推奨とします。
ちなみに下でも述べますが$(document).on("ready", fn)は僅かに意味が違っており、3.0で削除されました。

データについて

:warning: ダッシュ(ハイフン)を含む名前の.data()

jQuery 3.0では全てのdataの名前はキャメルケースで内部的に保持されます。
3.0でもケバブケース(ハイフンつなぎ)のdata名でのget/setは動作しますが、内部的にはキャメルケースになっており、.data()でdataオブジェクトを取り出すとそうなっていることが分かります。

var $div = $("<div />");

// ケバブケースでも動作する
$div.data("hover-count", 2);
$div.data("hover-count") // 2

// 内部的にはキャメルケースで管理
$div.data('click-count', 3);
var allData = $div.data();
allData.clickCount; // 3

Deferredについて

:warning: $.DeferredがPromises/A+互換に

$.Deferredが更新され、Promises/A+やES2015のPromiseと互換になりました。

  • Resolution

.resolve, .reject, .notifyは呼び出し元のDeferredオブジェクトのpromiseをcontextとして渡す代わりに、undefinedをcontextとして渡します。

$.Deferred().resolve().then(function () {
  console.log(this);
  /*
   * 3.0以前: thisは最初の$.Deferredオブジェクトのpromise
   * 3.0: undefinedのcontextが渡るのでthisはglobalのthis(ブラウザだとwindow)
   */
});

明示的にcontextを渡したい場合は.resolveWith, .rejectWith, .notifyWithを利用してください。

  • コールバックの終了

.then()関数に関して大きな変更があります。
.then()のコールバック関数の内で例外が発生した場合、rejectされる値に変換されます。
またrejectionを受けるハンドラからthenableでない値が返った場合、resolveされる値に変換されます。
promiseチェーンの最後に.catch()関数をつけることを 強く推奨 します。

jQuery 1.x, 2.xでは、.then()のコールバック関数の内で例外が発生した場合、コード実行が中断され、例外がtry/catchされるまで外側に伝播、もしくはwindowまでたどり着きwindow.onerrorを発生させていました。

$.ajax("/status")
  .then(function(data) {
      whoops(); // 存在しない関数を呼んで例外発生
      // 3.0以前の場合、ここでコードは中断される。
      // 3.0の場合、この関数のコードは中断されるがcatchに続く。
   })
   .catch(function(arg) {
      // 3.0以前の場合、このコードは実行されない。
      // 3.0の場合、このコードが実行される。argはErrorオブジェクト
   });
  • コールバックの呼び出し

Promises/A+の規格にはpromiseは常に1つの値でresolveされ、ハンドラの呼び出しはcontext無しで呼び出されると書いてあります。
しかしjQueryのDeferredはしばしばcontextを引き継いだり、複数の値をハンドラに渡したりしています。
3.0の.then()では1つ目の引数のみを受け取るようになっています。
後方互換性のために、contextや複数の値を受け取りたい場合は、古い.done().fail()関数を使ってください。

またPromises/A++準拠に際して.then()の呼び出しが常に非同期になりました(document-readyと同様です)。

  • 後方互換性

Deferredの.done(), .fail(), .pipe()関数は古い挙動のままにしてありPromises/A+互換ではありません。
非同期的なresolveや例外の変換が好ましくない場合は、.then(), .catch()の代わりにこれらを利用してください。

:warning: $.when()の引数

then関数を持つPromise互換のthenableならば何でも引数に取ることが出来るようになります。
ES2015のPromiseやBluebirdのpromiseなども利用できます。

さらにいうと、複数の引数を持つ$.when()Promise.allと同様に振る舞い、0または1つの引数の場合はPromise.resolveと同じ振る舞いをします。両方とも返り値として新たに生成されたDeferredオブジェクトを返します。

:warning: $.when()の進捗通知

3.0では$.when()の入力Deferredから出力Deferredへの進捗通知はなくなりました。Promises/A+の規格には進捗メッセージについての記載はありません。

要素サイズについて

:warning: .width(), .height()などが小数値を返すように

以前は常に整数値を返していましたが、3.0ではDOMのgetBoundingClientRectAPIを利用して小数値も返せるようになりました。

:warning: windowのouterWidth(), .outerHeight()にスクロールバーのwidth/heigthが含まれるように

$(window).width()はスクロールバーを含みませんが、CSSのmediaクエリはスクロールバーを含んで計算します。
CSSのmediaクエリと同様の値を取得するために$(window).outerWidth()はスクロールバーを含むようにしました。
window.innerWidthもこれと同じ値を持っています。

画面効果について

:warning: .show(), .hide(), .toggle()関数

これらの関数のソースコードの処理は、計算されたstyleではなくinlineのstyleをみるように修正されました。スタイルシートのdisplayの値を尊重することによりレスポンシブデザインとの互換性が上がりました。
inlineのdisplay:noneがない場合、非表示な要素でも、jQueryからは非表示と認識されません。
このようなjQueryに非表示と認識されない非表示要素を.show()やそれに似た関数(.fadeIn()など)で強制的に表示させることは出来ますが、このような表示/非表示の機能のサポートは止まりつつあり、利用をオススメしません。

前回の記事【翻訳まとめ】jQuery 3.0 alpha リリースノートに記載したとおり、"display:none"が定義された"hidden"クラスをaddClass/removeClassする方法をオススメします。

我々は、要素の表示状態とshow/hideアクションの全て関係を表した対応表を作りました。

:new: アニメーションにrequestAnimationFrameを使用

IE9以外のほぼすべてのブラウザでrequestAnimationFrameAPIがサポートされたので3.0からこれを利用します。
アニメーションがスムーズになりCPU消費が減少し、特にモバイル端末においてバッテリーの節約になります。
数年前にもこのAPIを利用しようとしましたが既存のコードとの深刻な互換性の問題により取り下げられました。
非アクティブなタブのアニメーションを停止することにより、この問題はほとんど解消されたと考えています。

:no_entry_sign: easing関数の引数

.animate()関数で利用されるアニメーション速度を定義するeasing関数の引数は、完了度合いを表すパーセンテージの1つのみになりました。

イベントについて

:warning: .load(), .unload(), .error()関数の削除

非推奨になっていたこれらの関数は削除されます。
イベントを付与する場合は.on()関数を利用してください。
例えば$("img").load(fn)は、$("img").on("load", fn)に変更してください。

:warning: .on("ready", fn)の削除

"ready"の名前がついたイベントを非対応とします。エラーになりやすく、1.8で非推奨となっていました。
安定に動作する$(fn)を利用してください。

:warning: event.pageXevent.pageYの独自実装の削除

サポートブラウザは全てpageXとpageYをサポートしたので、jQueryが他の値からこれを計算することはやめにしました。

:warning: $.event.props$.event.fixHooksの削除

イベントのプロパティ管理を整理し、イベント処理のパフォーマンスが向上しました。jQueryはpropertyの計算やコピー前もって行わず、最初にアクセスされた時に行うようにしました。
なのでポインターイベントのプロパティである$.event.props$.event.fixHooksは不要になりました。mouseHookskeyHooksも削除されました。これらに関するイベントは3.0でサポートしているからです。

:warning: 不正なセレクタへのイベントデリゲートは即座に例外

今まではイベントが発生してはじめてデリゲートされたセレクタを判別しており、不正な文法のセレクタがあるとデバッグすることが難しい状態でした。
3.0からはイベントが付与された際に前もってセレクタが不正な文法かどうかチェックされるようになります。

例:

// 3.0以前
$(document).on("click", "div:not", function() { // "div:not"は不正な文法
  console.log("到達しないコード");
});
console.log("イベント付与時に例外発生しない");

setTimeout(function() {
  try {
    $("div").click(); // クリックしてイベント発火
    console.log("実行時に例外発生しない");
  } catch(e) {
    console.log("実行時に例外発生する");
  }
}, 1000);

// コンソール出力
// => "イベント付与時に例外発生しない"
// => "実行時に例外発生する"

:no_entry_sign: .bind().delegate()の非推奨

1.7にて.on().off()が追加されました。
古い関数である.bind(), .unbind(), .delegate(), .undelegate()は非推奨とします。
まだ削除はされませんが、.on().off()を利用してください。

DOM操作について

:warning: .wrapAll(function)の挙動修正

今まで.wrapAll()の引数が関数だった場合、.wrap()と同じように振舞っていましたが、これを修正しました。
引数の関数は1度だけ呼ばれて、返り値のstringが意味する複数要素をwrapします。

オフセットについて

:warning: 不正な.offset()

.offset()を使う場合、jQueryコレクションの1つ目はDOM要素であることが必須となります。(厳密に言うとgetBoundingClientRect()関数を持つDOMですがサポートブラウザは全てこれを持っています)
そうでない場合は例外を発生します。

セレクタについて

:warning: :hidden:visibleの挙動

DOMのgetClientRect()関数がレイアウト値を返した場合、たとえそのDOMがheight/widthがゼロであってもvisibleと判断されます。
例えば<br />や空の<span />は高さがゼロですがvisibleです。

:warning: $("#").find("#")

"#"のみのセレクタは不正な文法としてエラーになります。

:new: 新しい$.escapeSelector()関数

この関数はセレクタ文字列に含まれるCSSで特殊な意味を持つ文字(ドットやセミコロン)をエスケープしてくれます。
例えば"abc.def"というidを持つ要素をjQueryで取得することは出来ませんでしたが、この関数を使って$("#" + $.escapeSelector("abc.def"))と取得することができます。

:no_entry_sign: $.expr[":"]$.expr.filtersの非推奨

この2つはjQueryのSizzleセレクタエンジンを通して自作セレクタを定義するものですが、$.expr.pseudosと重複しているので非推奨とします。

シリアライズについて

:warning: $.param()%20+に変換しない

formをPOSTする際のapplication/x-www-form-urlencodedではスペースは+に変換されるべきと記載があります。
今までこの変換を$.param()で行っていましたが、$.ajax()で行うようにしました。
$.param()はスペースを%20まで変換します。これは素のJavaScriptのencodeURIComponent()と互換があります。