jQuery Core 3.0 への更新方法や注意点の自分なりのまとめ
jQuery 3.0 では API の整理やバグ修正のため、 互換性の無くなる変更が公式 API 、非公式 API を問わず多く行われています。 そのため、jQuery 1.x(2.x)から 3.x に更新して問題が出ないように 更新ガイドが公式から出ています。
そのjQuery Core 3.0 Upgrade Guide や jQuery Migrate 3.x の警告文集 を読んで jQuery 3.x への更新方法や その際の注意点を自分なりに(今さらですが)まとめました。
以下のリストの「○」が付いている項目は jQuery Migrate プラグインが 警告してくれる項目です。「△」が付いている項目は部分的に警告してくれる項目です。 「◎」が付いている項目は Migrate プラグインが警告だけでなく動作の変更も行う 項目です(jQuery Migrate 3.x の警告文集から判断)。
- ブラウザサポート
- jQuery Migrate プラグインと3.0への更新手順
-
重要な変更の概要
- Ajax
- Attributes
- Callbacks
-
Core
- Breaking change: jQuery 3.0 は Strict Mode で実行されます
- Breaking change: document-ready ハンドラは常に非同期となった
- ○Breaking change:
jQuery.isNumeric()
と 独自の.toString()
- Breaking change: 廃止予定だった
.context
と.selector
プロパティが削除された - ○Breaking change: 廃止予定だった
.size()
が削除された - △Breaking change: 文書化されていない内部メソッドはもう外に晒しません
- Breaking change: 空の集合時の返り値は undefined です
- Feature: for...of ループが jQuery コレクションで使用可能に
- Feature:
jQuery.ready
promise が公式にサポートされる - ○Deprecated:
jQuery.unique()
がjQuery.uniqueSort()
に改名 - ○Deprecated:
jQuery.parseJSON()
- Deprecated:
jQuery(function)
以外の document-ready ハンドラの登録
- Data
- Deferred
- Dimensions
- Effects
- Event
- Manipulation
- Offset
- Selector
- Serialize
- Traversing
ブラウザサポート
jQuery 3.0 からは以下のブラウザがサポートされます:
- Internet Explorer は 9 以上
- Chrome, MS Edge, Firefox, Safari は 最新とそのひとつ前のバージョンまで
- Opera は最新バージョン
- iOS の Safari は 7 以上
- Android は 4 以上
IE は 8-10 、Android 標準ブラウザは 4.3 以前が Microsoft や Google による サポートが行われていませんが、jQuery では一部サポートされています。
これはメジャーバージョンの更新でのみサポートするブラウザの変更を行う方針のためと 思われます。 少なくとも jQuery 4 が出てくるまで上のリストのブラウザをサポートするそうです。
リストに戻るjQuery Migrate プラグインと3.0への更新手順
jQuery 1.9(2.0) の時とは別に、3.0 への移行を補助するための jQuery Migrate プラグイン 3.xが新しく用意されていて、 これを利用することが推奨されています。
これは 3.0 への移行後に問題が起こる恐れのあるコードを指摘したり削除された 機能を復元したりしてくれますが、jQuery 1.9(2.0) の時のような過去に 変更された振る舞いについては警告したり修復したりはしないそうです (実際は一部行うが、しないと見なした方が無難です)。
更新ガイドには jQuery 1.11.0(2.1.0) 以降で使えると書いてありましたが、一方 Github のページでは 1.12.x(2.2.x) と書かれています。
そのため、jQuery 1.x(2.x) の最新版に更新してから使う方が無難でしょう。1.x(2.x)の 最新版への更新には jQuery Migrate プラグイン 1.x が利用できます。
jQuery 3.0 への更新手順は以下のようになります。
ページ上の jQuery のバージョンを1.x(2.x)の最新バージョンに 更新します(最新版は例えばjQuery CDN から入手できます)。
jQuery Migrate プラグイン 1.xの非圧縮版をページに追加します。
(この手順は必須ではないですが推奨されています。) 使用している他の jQuery プラグインを最新バージョンに更新して、jQuery の 最新バージョンとの互換性を高めます。 プラグインの互換性については個々のプラグインのページを 確認してください。
ページをテストして、コンソールに書き出される警告を全て解決します。 警告文の詳細についてはこちら(自分が訳した記事は こちら)に書いてありますので、参考にして下さい。
jQuery Migrate 1.x を削除して、最新の jQuery 1.x(2.x) だけで ページの jQuery のコードが正しく動くことを確認してください。 (動かない場合はリリースノートを参考にするなどして地道に修正します)
ページの jQuery のバージョンを 3.x に更新します。そして、 jQuery Migrate 3.x の非圧縮版をページに追加します。
ページをテストして、コンソールで警告される問題を全て解決します。 警告文の詳細についてはこちら(自分が訳した記事は こちら)に書いてありますので、参考にして下さい。 他の jQuery プラグインに因る不具合についてはそのプラグインの製作者に 報告するなどして下さい。
jQuery Migrate 3.x を削除して、jQuery 3.x だけでページの jQuery のコードが正しく動くことを確認して下さい。 (動かない場合はリリースノートを参考にするなどして地道に修正します)
同じページ上で Migrate 1.x と Migrate 3.x を同時に実行することはサポートされていませんので、 上のように段階を踏んでバージョンアップします。
Migrate プラグインの開発バージョンは圧縮されておらず、 使用した機能が廃止予定であったり削除されている場合、 コンソールに警告を出力します。 そのため 移行の際、既存の jQuery のコードやプラグインのデバッグに役立ちます。
一方、圧縮された Migrate プラグインは警告を発しません(1.4.0 以降は インストールされた旨を伝えるメッセージのみ出力されます)。こちらは jQuery 3.0 以上を使いたいのに古い互換性の無いコードやプラグインを 使わざるを得ないサイトに利用できます。 古い挙動を修復した場合、新しい挙動を前提にしたコードと衝突するかもしれないので、 一時しのぎとして使うのが理想的です。
リストに戻る重要な変更の概要
大量にあるように見えますが、大半は極端な事例で、修正箇所は少ないだろうと いうことです。
変更は jQuery のコンポーネントカテゴリごとに羅列され、 項目の先頭にその変更の影響度や性質を示す記述が以下のように付けてあります。
Breaking change: 既存のコードに影響を与える恐れがある変更です。 何らかの形で API の周知の部分が変更されています。前述したように その影響は大体の場合、特定の極端な事例に対してのみだそうです。
Feature: API の追加です。既存のコードに影響はほぼ与えないでしょう。 しかしながら、追加機能が既存のコードに悪い作用を与える可能性はあります。
Deprecated: jQuery 3.0 にはまだ存在しているが非推奨である機能や API です。 将来のメジャーバージョンの更新で削除される可能性があります。
上述した jQuery Migrate プラグインがこれらの変更の大半を特定し警告できますので コードの中のこのような変更は修正可能であることを頭に入れておいてください。
変更の完全で詳細なリストについては、 jQuery Core の マイルストーン、もしくは そのバージョンの diff を見て下さい。
※jQuery Migrate プラグイン 3.0.0 で警告される場合はその旨を書いてあります。
リストに戻るAjax
Breaking change: jQuery.ajax からの Deferred の特殊なケース用メソッドを削除
jQuery.ajax()
は jqXHR オブジェクトを返しますが、これは jQuery の
Deferred オブジェクトで、success、error、complete という名のメソッドが
追加されていました。
これらの名はjQuery.ajax()
への引数オブジェクトにもあり
混乱を招いたそうで、且つ jqXHR オブジェクトは Deferred のように扱われるべき
ということから、jQuery 3.0 以降 jqXHR オブジェクトのこれら3つのメソッドは
削除されました(jQuery.ajax()
への引数オブジェクトにある同名の
コールバックは削除されません)。
代わりとして、Deferred の標準メソッドである done、fail、always を使うか、 Promises/A+ 準拠の then や chatch メソッドを使ってください。
https://github.com/jquery/jquery/issues/2084
※Migrate プラグインで警告されます。
リストに戻るBreaking change: クロスドメインのスクリプトをリクエストする時は宣言しなくてはならない
異なるドメインの script を取得するために
jQuery.ajax()
やjQuery.get()
を使ってリクエストを生成する時、
必ず明確にdataType: "script"
と指定することになりました。
これは、最初は script ではないコンテンツを配信していたサイトが後になって 悪意を持つ script にすり替えて攻撃してくる芽を摘み取るためです。
jQuery.getScript()
は明確にdataType: "script"
をセットするので
この変更の影響を受けません。
Breaking change: URL 内のハッシュはjQuery.ajax()
を実行しても温存される
jQuery.ajax()
は渡された URL にハッシュがあっても取り除かなくなり、
URL 全体を(xhr, script, jsonp, またはカスタムで)送信するようになりました。
もしその送信先のサーバが URL のハッシュを扱うことができない場合は、 リクエストを送る前にハッシュを取り除く必要が出てきます。
https://github.com/jquery/jquery/issues/1732
リストに戻るFeature: jQuery.get()
とjQuery.post()
に新しい用法
jQuery 3 では
jQuery.ajax()
に渡す settings オブジェクトと同じものが
jQuery.get()
とjQuery.post()
にも渡せるようになりました。
https://github.com/jquery/jquery/issues/1986
リストに戻るAttributes
Breaking change: .removeAttr()
がプロパティに false をセットしなくなった
jQuery 3.0 より前は、checked、selected、readonly のような真偽値の属性に対し
.removeAttr()
を使うと同名のプロパティにfalse
を設定することも行いました。
この動作は Internet Explorer の古いバージョンに必要だったそうですが、 そもそも属性は初期値を表しプロパティは現在の(動的な)値を表すため、 モダンブラウザにおいてこの動作は正しくないので行われなくなりました。
DOM 要素に.removeAttr("checked")
等を実行することはまずしません。
.prop( "checked", false )
を使ってください。唯一の例外は DOM 要素の現在の状態を
HTML ソースにシリアライズする場合で、この場合属性がシリアライズされるので
.removeAttr("checked")
等を実行する場面が出てきます。
https://github.com/jquery/jquery/issues/1759
https://github.com/jquery/jquery/issues/2913
※Migrate プラグインで警告されます。
リストに戻るBreaking change: 全く選択されていない<select multiple>
は空配列を返す
jQuery 3.0 より前は、どの要素も選択されていない<select multiple>
要素に
.val()
を実行するとnull
が返されていました。もし一つでも要素が
選択されていた場合は返り値が配列となるのでこの挙動は不便でした。
それに加えて、全ての<option>
要素が無効な時は空配列を返していましたので、
一貫性をより持たせる点からも、何も選択されてない場合でも空配列を返すように
なりました。
https://github.com/jquery/jquery/issues/2562
リストに戻るFeature: SVG 文書でも class の操作がサポートされる
jQuery は 3 でも SVG をフルサポートしていませんが、jQuery のメソッドの多くは
SVG 文書でもうまく動くそうです。なかでも.addClass()
や.hasClass()
のような
class 名を取り扱うメソッドは、jQuery 3 からは SVG でもサポートするそうです。
https://github.com/jquery/jquery/issues/2199
リストに戻るDeprecated: 引数無しの .toggleClass() と .toggleClass( Boolean )
上の2つの用法が jQuery 3 で廃止予定になりました。この用法はドキュメントに 記載されていましたが、その挙動は十分に定義されたものではなかったそうです。
不正な用法ですが、.toggleClass( undefined )
と実行する形で
無自覚にこの引数無しでの呼び出しを使っているかもしれません。
※Migrate プラグインで警告されます。
リストに戻るCallbacks
Feature: Callbacks のlock()
が防ぐのは将来のリストの実行だけ
もし Callbacks オブジェクトが、
.fire()
が実行された後に.lock()
を呼び出すようなハンドラ関数を持っていたら、
.lock()
は将来のコールバックのリストの実行を止めるのみで、
現在のリストの実行を即座に中断しないそうです。
現在の実行を止めるためには、オプションstopOnFalse
を使ってください。
https://github.com/jquery/jquery/issues/1990
リストに戻るCore
Breaking change: jQuery 3.0 は Strict Mode で実行されます
jQuery 3.0 がサポートするブラウザは大体"use strict"
が使えるので
jQuery は現在このディレクティブを付けてビルドされています。
他のコードも Strict Mode で実行する必要があるわけではないので、既存のコードに 変更を加える必要はないそうです。
ただし、開発環境の中でデバッガ等が Strict Mode に違反する機能(例として
ASP.NET 4.0 が使うarguments.caller.callee
を挙げています)を使っている場合は
jQuery 3 未満を使い続けることになります。
最近のブラウザはerror.stack
を通してのスタックトレースをサポートしているので
arguments.caller.callee
を探る必要は無いでしょう。
https://github.com/jquery/jquery/pull/3061
https://bugs.jquery.com/ticket/13335
Breaking change: document-ready ハンドラは常に非同期となった
jQuery の document-ready は jQuery 1.6 から jQuery.Deferred を使って実現されて ましたが、jQuery 3.0 で Promises/A+ 標準に則したものになったことにより、 document-ready ハンドラは常に非同期で実行されるようになりました。
これは、たとえ document-ready ハンドラを document が既に準備された後で追加しても非同期で実行されるということです。 例として、以下のコードが挙げられていました。
$(function(){
console.log("ready");
});
console.log("outside ready");
jQuery 3.0 より前では document の状態によって
"outside ready"
と"ready"
がログ出力される順番が変わっていました。
jQuery 3.0 では document が準備されているかどうかに関わらず常に
"outside ready"
、"ready"
の順にログ出力されます。
加えて、今はハンドラ群がそれぞれ独立して実行するようになったので、 ある document-ready ハンドラでの例外やエラーが 他の document-ready ハンドラ群の実行を妨げるようなことは無くなったそうです。
ちなみに、カスタムビルドで deferred モジュールを除外した場合、もう一つの
document-ready 実装が使われます。この実装ではjQuery.ready
という promise ライクな
オブジェクト(Thenable)をサポートし、これを使って document-ready を実現します。
jQuery.when( jQuery.ready ).then( aHandler ) )
https://github.com/jquery/jquery/issues/1823
https://github.com/jquery/jquery/pull/2891
Breaking change: jQuery.isNumeric()
と 独自の.toString()
jQuery.isNumeric()
は以前は.toString()
メソッドを持つオブジェクトから
数値を取得しようとしていましたが、今ではもう
プリミティブな数値と文字列以外はfalse
を返すようになりました。
そのため、独自の.toString()
を持つオブジェクトの
バリデーションは自前で行う必要があります。
https://github.com/jquery/jquery/issues/2662
※Migrate プラグインで警告されます。
リストに戻るBreaking change: 廃止予定だった.context
と.selector
プロパティが削除された
これらのプロパティは jQuery 1.9 で廃止予定になっていました。
これらは既に削除されていた.live()
にのみ利用されていて
jQuery Migrate プラグインで.live()
を復元するのに使っていました。
そして現在のコレクションの context や selector を正確に表しませんでした。
https://github.com/jquery/jquery/issues/1908
リストに戻るBreaking change: 廃止予定だった.size()
が削除された
.size()
は jQuery 1.8 以降で廃止予定となり jQuery 3.0 で削除されました。
代わりに.length
プロパティを使ってください。
※Migrate プラグインで警告されます。
リストに戻るBreaking change: 文書化されていない内部メソッドはもう外に晒しません
jQuery 3.0 では以下のメソッドを内部使用のみにし外部に晒さないようにしました。 ドキュメントにも記載されません。
- jQuery.swap
- jQuery.buildFragment
- jQuery.domManip
https://github.com/jquery/jquery/issues/2224
https://github.com/jquery/jquery/issues/2225
※Migrate プラグインで jQuery.swap だけ警告されます。
リストに戻るBreaking change: 空の集合時の返り値は undefined です
API のガイドライン
https://github.com/jquery/jquery/wiki/API-design-guidelines に合わせて
以下の API が実行時に空のコレクションの場合undefined
を返すように変更されました。
寸法を測るメソッド:
.width()
,.height()
,.innerWidth()
,.innerHeight()
,.outerWidth()
,.outerHeight()
オフセットを測るメソッド:
.offsetTop()
と.offsetLeft()
これらのメソッドは、以前は空のコレクションに対してnull
を返していました。
https://github.com/jquery/jquery/issues/2319
リストに戻るFeature: for...of ループが jQuery コレクションで使用可能に
jQuery 3.0 では ES2015 で導入した for...of ループがサポートされます。 for...of は Array, Map, Set を含む iterable なオブジェクトに対して ループ処理できます。このループで取得する値は jQuery コレクションの DOM 要素で、一度に一個です。
※for...of を使うには ES2015 をサポートする環境か Babel のような トランスパイラを用いる必要があります。
以下は挙げられていた例です:
var elems = $(".someclass");
// 以前の jQuery での方法
$.each(function(i, elem) {
// elem (もしくは this オブジェクト)で何か処理
});
// よりいけてる ES2015 での方法
for ( let elem of elems ) {
// elem で何か処理
}
https://github.com/jquery/jquery/issues/1693
リストに戻るFeature: jQuery.ready
promise が公式にサポートされる
jQuery 1.8 から jQuery.ready
は promise のようなオブジェクト
(Promise の用語で"thenable")として使われてきましたが、
jQuery 3.0 から
jQuery.when()
やネイティブのPromise.resolve()
を通しての
このオブジェクトの使用が
サポートされます、とドキュメントに記載されます。
jQuery.when()
等に通すようにすれば、このオブジェクトが jQuery の Deferred なのか
ネイティブの Promise のように promise タイプの他のオブジェクトなのかを考える必要が
なくなります。
使用法として以下が挙げられています:
$.when( $.ready, $.getScript("optional.js") ).then(function() {
// document が準備され optional.js が読み込まれ実行された
}).catch( function() {
// エラー発生
});
https://github.com/jquery/api.jquery.com/pull/530
リストに戻るDeprecated: jQuery.unique()
が jQuery.uniqueSort()
に改名
その振る舞いを理解し易くするためjQuery.unique()
を
jQuery.uniqueSort()
に改名しました。機能の変更はなく、改名しただけです。
jQuery.unique()
は廃止予定になりました。
※Migrate プラグインで警告されます。
リストに戻るDeprecated: jQuery.parseJSON()
jQuery 3.0 がサポートするブラウザは全てネイティブのJSON.parse()
メソッドを
サポートしているので、jQuery.parseJSON()
は廃止予定になりました。
https://github.com/jquery/jquery/issues/2800
※Migrate プラグインで警告されます。
リストに戻るDeprecated: jQuery(function)
以外の document-ready ハンドラの登録
互換性の問題に対処してきた歴史から、 document の ready ハンドラを設定する方法が
沢山あります。以下のコードは全て同じ意味で、document が準備された時に
関数fn
を実行します:
$(fn);
$().ready(fn);
$(document).ready(fn);
$("selector").ready(fn);
上のうち、jQuery 3.0 から推奨される方法は最初の$(fn)
だけです。
後の Event の節で書かれますが、$(document).on("ready", fn)
という形は
わずかに振る舞いが異なるため jQuery 3.0 で削除されています。
Data
Breaking change: .data() のダッシュを含む名前について
jQuery 3.0 から data のキー名は全て、jQuery 内部の data オブジェクトに ケバブケース(例、click-count)ではなく、キャメルケース(例、clickCount)で 保存されます。
これは JavaScript のプロパティのため、ダッシュ付きの CSS のスタイル名や data 属性名をキャメルケースに変える DOM 標準での方法と一致しています。
ケバブケースの使用は、例えば.data("right-aligned")
という風に .data() API を
使ってデータ項目の設定や取得をする場合は、jQuery 3.0 でも動きますが、
その時内部の data オブジェクトのそのデータ項目は
キャメルケース(rightAligned)で保存されるようになっています。
jQuery 3.0 での主な違いは .data() API を使わないで data オブジェクトに直接 ケバブケースの名前で取得・設定する場合です。
挙げられてた例:
var $div = $("<div />");
$div.data("clickCount", 2);
$div.data("clickCount"); // 2
$div.data("click-count", 3);
$div.data("clickCount"); // 3, ケバブケースはキャメルケースに変換される
$div.data("click-count"); // 3
var allData = $div.data();
allData.clickCount; // 3, キャメルケースで保存される
allData["click-count"]; // undefined
allData["click-count"] = 14;
$div.data("click-count"); // 3, jQuery2.xでは14だった
allData.clickCount; // 3
allData["click-count"]; // 14
https://github.com/jquery/jquery/issues/2070
https://github.com/jquery/jquery/issues/2257
https://github.com/jquery/jquery/issues/1751
※Migrate プラグインで jQuery.data() でのみ警告されます。 jQuery.fn.data() で警告されません(jQuery Migrate 3.0.0 時点)。
リストに戻るDeferred
Breaking change 且つ Feature: jQuery.Deferred
はもう Promises/A+ 互換です
Deferred は Promises/A+ と ES2015(ES6として知られる)のPromise と互換性を 持つように更新されました。
https://github.com/jquery/jquery/issues/1722
https://github.com/jquery/jquery/issues/2102
Resolution
.resolve()
, .reject()
, .notify()
は
コールバックのコンテキスト(this)に、それらメソッドと結びついている
Deferred オブジェクトの promise が設定されていましたが、これからは
特に設定されないようです。
コンテキストを設定するには、.resolveWith()
, .rejectWith()
,
.notifyWith()
を使ってください。
https://github.com/jquery/jquery/issues/3060
リストに戻るコールバックでのエラーについて
.then()
には大きな変更が施されました。
特に、.then()
のコールバックの中で throw された例外は catch されて
reject の値に変換されるようになり、
そしてreject 側のハンドラから返される thenable でない値は
resolve の値になります。
デバッグを容易にするため(3.0 で導入された).catch()
を
promise チェーンの最後に加えることが強く推奨されています。
jQuery.ajax()
から返される jQXHR オブジェクトが jQuery.Deferred の
スーパーセットなので、このオブジェクトを使う時に振る舞いの変更に遭遇することが
多いと推測されます。
jQuery 1.x と 2.x では、コールバック関数の内部で発生した例外は catch されないとコードの実行が止まり、 その例外は try/catch 節に catch されるまで浮き上がっていき、 浮き上がりきって window にたどり着くと window.onerror を引き起こしていました。
例えば、新しく標準 Promise/A+ の振る舞いに準拠した以下のコードの場合は:
$.ajax("/status")
.then(function(data) {
whoops();
// コンソールに "jQuery.Deferred exception: whoops is not a function"
// と表示され、この関数の以降のコードは実行されない
})
.catch(function(arg) {
// 上のエラーの後にこのコードが実行される
// arg は Error オブジェクト、"whoops is not a function"
});
となりますが、古いスタイルの Deferred メソッドの場合だと以下のようになります:
$.ajax("/status")
.done(function(data) {
whoops();
// コンソールに"whoops is not a function"と表示され
// この関数の以降のコードは実行されない
})
.fail(function(arg) {
// 例外が catch されなかったのでこのコードは実行されない
});
Deferred の中で JavaScript の例外が発生した場合、jQuery は コンソールにメッセージを出力することに注意して下さい。 メッセージは jQuery.Deferred exception: (error message) という形になります。
もしこのような例外でメッセージを出力してほしくないのなら、
jQuery.Deferred.exceptionHook
をundefined
に設定してください。
この種のエラーの特定にもう少し助けが欲しいなら、 jquery-deferred-reporter プラグインで スタックトレースが得られますので、開発中に使用して下さい。
https://github.com/jquery/jquery/issues/2736
リストに戻るコールバックの起動について
Promises/A+ の仕様では、promise は常に一つの値に解決され、そしてハンドラは
this
コンテキスト無しで呼び出される、としています。一方 jQuery Deferred は
ハンドラにコンテキストを渡したり複数の値を渡したりします。
しかし大半の場合、渡される値の中で第一引数が最も重要なものになっています。 他の Promises/A+ 実装と jQuery のそれを混在しているなら、 ハンドラで第一引数だけを受け取るようにしても大丈夫です。
もし既存のコードと完全に互換性を維持したいなら、
jQuery Deferred だけを使うようにし、古いメソッドの.done()
と.fail()
に
切り替えて下さい。これらは後方互換性を持つ振る舞いを全て保持しています:
// Promises/A+ と互換性のない 以前の .then() の典型的な使用法
$.ajax("url").then(
// success
function( data, textStatus, jqXHR ) { /* code */ },
// error
function( jqXHR, textStatus, errorThrown ) { /* code */ }
);
// 前の振る舞いを維持するために以下のように書き換える
$.ajax("url")
// success
.done(function( data, textStatus, jqXHR ) { /* code */ })
// error
.fail(function( jqXHR, textStatus, errorThrown ) { /* code */ });
もう一つ Promises/A+ 準拠のために施した振る舞いの変更として、
Deferred の.then()
のコールバックは常に非同期で呼ばれるようになりました。
以前は、.then()
のコールバックを既に resolve / reject された
Deferred に追加した場合、コールバックはすぐに同期的に実行されていました。
後方互換性
Deferred のメソッド.done()
、.fail()
、 .pipe()
は以前の挙動を保持しています
(そのため Promises/A+ 準拠ではありません)。
ただし.pipe()
は deprecated になっています。
もし古い振る舞いが必要な場合は.then()
や.catch()
の代わりに
これらのメソッドを使うことができます。
まとめ
まとめると、
.resolve()
,.reject()
,.notify()
からのコールバックのコンテキストは 特に設定されなくなった.then()
のコールバックから throw される例外は catch されて reject の値に 変換されるようになった.then()
の reject 側のハンドラから返される thenable でない値は resolve の値になる- Deferred の中で例外が発生した場合、 コンソールに jQuery.Deferred exception: (error message) という メッセージが出力される
- デバッグの助けにjquery-deferred-reporter プラグイン
.then()
のコールバックは常に非同期で呼ばれるようになった。.done()
、.fail()
、.pipe()
は以前の挙動を保持している。
Breaking change 且つ Feature: jQuery.when() の引数
jQuery.when()
は Promise 互換の"thenable"
(then()が定義されているオブジェクトや関数)を引数として
受け入れるようになりました。そのため、ネイティブの ES6 の Promise や
Bluebird の promise なども受け入れることができます。
加えてjQuery.when()
への引数が複数であるか、もしくは単数・無しかで
その振る舞いが異なるようになりました。
引数を複数渡した場合は、resolve の値を集約する(jQuery 特有の拡張によって
resolve の値が複数でも大丈夫です)、Promise.all
と同じように振る舞います。
渡された promise がひとつでも失敗すると、最初の失敗時の値で reject されます。
単一のまたは引数無しでの呼び出しでは、thenable や Promise ライクが渡された場合は
それとほぼ同価値の Deferred を返し、それ以外が渡されればその値で resolve
された Deferred を返す、Promise.resolve()
と同じように振る舞います。
jQuery 3.0 から、これら両方とも新しい Deferred を返します。以前のバージョンでは 単一の Deferred を渡したときは新しく Deferred を作成しませんでした。
https://github.com/jquery/jquery/issues/2018
https://github.com/jquery/jquery/issues/2546
https://github.com/jquery/jquery/issues/3029
Breaking change: jQuery.when() の progress 通知
jQuery 3.0 から、jQuery.when()
は受け取った Deferred から
返り値の新規 Deferred へ progress の通知を行わなくなりました。
progress メッセージは Promises/A+ 仕様には無く、 この progress 通知の振る舞いは jQuery API に文書化されませんでした。
https://github.com/jquery/jquery/issues/2710
リストに戻るDimensions
Breaking change: .width()
, .height()
, .css("width")
, .css("height")
は数値でない値を返すことがあります
バージョン 3.0 以前、jQuery は DOM のoffsetWidth
とoffsetHeight
プロパティを要素の寸法を測定するのに使っていました。これらのプロパティは
常に数値を返します。
jQuery 3.0 では DOM の getBoundingClientRect API を通すようになりました。 これはより詳細な値が得られる代わりに数値でない可能性があります。
もし常に数値が返る事を前提にしてコードが書かれている場合は、 この変更に対応するように調整する必要があるかもしれません。
※この変更は CSS transform で拡大縮小を使っていて
且つauto
が指定されたインライン要素の大きさを取得したい場合
一貫性のある詳細な値が取得できないことで問題になっているようです。
https://github.com/jquery/jquery/issues/1724
リストに戻るBreaking change: window の .outerWidth() や .outerHeight() はスクロールバーの幅/高さを含みます
$(window).width()
と実行すると、コンテンツがその要素の高さを超える場合、
ブラウザが加えたスクロールバーを除外した"content width" が返ります。
これはスクロールバーの幅を含む、 CSS が media query で使う幅と異なります。
CSS の media query の幅の概念に沿う測定メソッドを提供するために、
$(window).outerWidth()
はスクロールバーを含んだ幅を返すようになりました。
これは DOM のwindow.innerWidth
プロパティと同じです。
.outerHeight()
にも同じことが当てはまります。
https://github.com/jquery/jquery/issues/1729
リストに戻るEffects
Breaking change: .show()
, .hide()
, .toggle()
はスタイルシートの変更により配慮するようになった
要素を表示・非表示するための jQuery のコードが、計算後のスタイルよりも インラインに注目するように更新されました。
レスポンシブデザインのテクニックとして、アクティブなスタイルシートのルールが デバイスの向きの変化やwindow のサイズ変更などを期に動的に変わる可能性があって、 この技術との互換性を増すために可能な時はスタイルシートの display の値に 配慮するようになったそうです。
その結果、DOMツリーに接続されてない要素は、その要素がインラインで且つ
display:none
を持たない限り、非表示と見なさなくなりました。
そしてそのため.toggle()
は jQuery 3.0 から
DOMツリーに接続されてない要素と接続された要素を区別しなくなりました。
.show()
やそれと類似したメソッドは、
スタイルシートのルールによって非表示になっている要素でもその表示・非表示を
強制することができるでしょう。
しかし、この機能のサポートによって全ての表示・非表示の処理を遅くさせるため
その使用は推奨されません。
非表示にした要素を再表示する時に、前の計算値で display が復元される ことを前提にしているコードは再検討する方がいいでしょう。また、 DOMツリーに接続していない要素が非表示のように扱われることを 前提にしているコードも再検討する方がいいでしょう。
参考として、display の状態が.show()
、.hide()
の実行でどのようになり得るか、
その可能性を網羅した表が挙げられています。
Feature: アニメーションで requestAnimationFrame を再び使うようになった
jQuery は現在、アニメーションで requestAnimationFrame を 使うようになりました(IE 9 のような未サポートのブラウザは別)。 これでアニメーションがよりスムーズに、且つ CPU 負荷も少なくなり、 モバイルデバイスではバッテリーの消費も少なくなります。
jQuery は 1.6 の時に requestAnimationFrame を導入しましたが、タブ非表示時に 深刻な互換性の問題があることが発覚して1.6.3で元に戻していました。 それらの問題の大半をブラウザのタブが表示されてない間は アニメーションを停止することで解決したそうです。
ですので、アニメーションが常に実行されているとは限らないことに注意して コードを書く必要があります。
リストに戻るDeprecated: jQuery.fx.interval
前項で書いたように requestAnimationFrame をアニメーションで使うようになったので
jQuery.fx.interval
プロパティは大半のブラウザで無視されます。
jQuery 3.0 ではまだ存在して IE9 のようなブラウザで使われていますが、
将来のメジャーバージョンのリリースで削除するつもりだそうです。
※Migrate プラグインで警告されます。
リストに戻るDeprecated: easing 関数の第2引数以降
.animate()
がその中で呼ぶ easing 関数は引数として完了までの割合が渡されます。
第2引数以降にはその割合から導き出した値が渡されています。
第2引数以降は将来のメジャーバージョンの更新で削除されるかもしれないそうです。
前の easing の例:
$.easing.easeInOutSine = function (x, t, b, c, d) {
return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
};
書き直された等価の easing メソッド:
$.easing.easeInOutSine = function (x) {
return -0.5*(Math.cos(Math.PI*x) - 1);
};
https://github.com/jquery/api.jquery.com/issues/912
※Migrate プラグインで警告されます。また、
第2引数以降を使う easing 関数が"linear"
に
換えられてしまうのでその場合は修正する必要があります(参考)。
Event
Breaking change: .load()
, .unload()
, .error()
が削除された
これらの関数はイベント登録のショートカットですが、
ajax の.load()
と競合したり API の制限がありました。
これらの代わりとして、.on()
を使ってください、例えば
$("img").load(fn)
は$("img").on("load", fn)
と変えて下さい。
https://github.com/jquery/jquery/issues/2286
※Migrate プラグインで警告されます。
リストに戻るBreaking change: .on("ready", fn)
が削除された
jQuery は"ready"
という名の独自イベントをサポートしなくなりました。
このイベントは document が ready になる前にアタッチされた場合のみ
コールバックが実行されるため error を起こしやすかったそうで、
jQuery 1.8 で廃止予定になっていました。
代わりに$(fn)
を使ってください。
https://github.com/jquery/jquery/issues/2264
※Migrate プラグインで警告されます。
リストに戻るBreaking change: event.pageX
とevent.pageY
の正規化が削除された
jQuery 3.0 が公式にサポートするブラウザでは Event の pageX と pageY プロパティを 提供します。 jQuery は他のプロパティからこれらのプロパティの値を導出していましたが、 そのコードは削除されました。
この変更は主流のブラウザに影響は無いでしょうが、 これらのプロパティが存在しないようなマイナーな環境を見つけたら、 知らせてほしいそうです。
https://github.com/jquery/jquery/issues/3092
リストに戻るBreaking change: jQuery.event.props
とjQuery.event.fixHooks
が削除された
Event のプロパティの管理法を見直すことで jQuery のイベント処理の性能が向上したそうです。今までは前もってプロパティ群を 算出したりコピーしたりしていましたが、最初にアクセスされた時に そのプロパティだけを算出もしくはコピーするようになりました。
この性能向上は特に、算出するのにレイアウト計算が発生するようなプロパティを イベントハンドラが必要としていない場合で大きくなります。 pointer イベント関連用のプロパティ追加がよく知られていましたが、それらの イベントは jQuery 3.0 ではサポートされているのでもう必要ありません。
jQuery Migrate プラグインを使うとjQuery.event.props
と
jQuery.event.fixHooks
プロパティは復元できます。
ちなみにドキュメントには載っていなかったmouseHooks
とkeyHooks
も
同様に削除されたそうです。
https://github.com/jquery/jquery/issues/3103
https://github.com/jquery/jquery/issues/1746
https://learn.jquery.com/events/event-extensions/
※Migrate プラグインで警告されます。
リストに戻るBreaking change: 不正なセレクタでのイベントの delegate はすぐに throw する
jQuery 3.0 以前は、delegate されたイベントで使用したセレクタは最初にその要素上で イベントが発生するまでは使われなかった。このため delegate した時間と場所からかけ離れたところでエラーが発生した場合 デバッグが困難になる時がありました。
今ではイベントが delegate された時にセレクタをテストして、 そのセレクタが不正ならばエラーを throw するようになりました。
この変更が Breaking change になっているのは、決して発生しないイベントを 追加した場合でも不正なセレクタを使うとエラーが throw されるからです。 以前はその場合不正なセレクタを使ってもエラーは throw されませんでした。
https://github.com/jquery/jquery/issues/3071
リストに戻るDeprecated: .bind()
と.delegate()
jQuery 1.7 で.on()
がイベントハンドラの追加用として導入されました。
.bind()
,.unbind()
,.delegate()
,.undelegate()
は 3.0 から廃止予定に
なりました(まだ存在しています)。
.on()
や.off()
への書き換え方は API ドキュメントで説明されています。
※Migrate プラグインで警告されます。 過去に書いたjQuery Migrate の記事にも書き換え方が載っています。
リストに戻るManipulation
Breaking change: .wrapAll(function)
はその関数を一回だけしか呼ばない
前のバージョンでは.wrapAll()
に関数が渡された時、.wrap()
のように
振る舞っていました。つまり、コレクションの要素ごとに渡された関数が呼ばれていました。
現在の.wrapAll(function)
は、
渡された関数を一回だけ実行して、
その返り値を使ってコレクション全体を包むようになりました。
https://github.com/jquery/jquery/issues/1843
リストに戻るOffset
Breaking change: .offset()
への不正な入力
.offset()
を使うとき、jQuery オブジェクトが保持するコレクションの最初の項目が
getBoundingClientRect()
を持つ DOM 要素でなければなりません
(jQuery 3.0 がサポートするブラウザは全てこの API を使えます)。
また、その要素は表示されており、その時点で document 上に 存在していなければならない(例、DOM ツリーに非接続ではいけない)ことに注意して下さい。
それ以外だと jQuery がエラーを throw することになるかもしれません (この状況でどうなるかを jQuery は定めていません)。
https://github.com/jquery/jquery/issues/2115
https://github.com/jquery/jquery/issues/2114
※Migrate プラグインで警告されます。
リストに戻るSelector
Breaking change: :hidden
と:visible
の振る舞い
要素が DOM のgetClientRects()
からレイアウトボックスを取得できるなら、
そのレイアウトボックスの高さや幅が 0 だったとしても、その要素は表示されている
と見なされるようになりました。
そのため<br />
要素や空の<span>
要素などでも表示されていると見なされます。
https://github.com/jquery/jquery/issues/2227
https://github.com/jquery/jquery/issues/2604
Breaking change: jQuery("#")
と.find("#")
は不正な構文
jQuery 3.0 ではセレクタがハッシュマーク(#)のみの場合は構文エラーを
throw するようになりました。
前のバージョンでは、$("#")
は空のコレクションを返し、
.find("#")
はエラーを throw していました。
https://github.com/jquery/jquery/pull/1682
リストに戻るFeature: 新メソッドjQuery.escapeSelector()
jQuery.escapeSelector( selector )
はセレクタの文字列を引数に取り
CSS セレクタにおいて特別な意味を持つ文字を全てエスケープします。
これは本質的には
CSS ワーキンググループのCSS.escape()
を
jQuery のサポートするブラウザで実行できるようにした shim です。
このメソッドは class 名や ID にドットやセミコロンのような CSS で特別な意味を持つ文字を含む場面で役に立ちます。
例えば、もし"abc.def"
という id の要素を選択したい場合、
$( "#abc.def" )
とするとそのセレクタは「id が'abc'
で且つクラス'def'
も持つ
一つの要素」と解釈されるので選択されませんが、
$( "#" + $.escapeSelector( "abc.def" ) )
とすれば選択できます。
https://github.com/jquery/jquery/issues/1761
リストに戻るDeprecated: jQuery.expr[":"]
とjQuery.expr.filters
jQuery で Sizzle セレクタエンジンを通してカスタムセレクタを追加する方法は
複数ありますが、標準はjQuery.expr.pseudos
を使うことだそうです。
これのエイリアスであるjQuery.expr[':']
とjQuery.expr.filters
は
廃止予定になりました(まだ使えます)。
※Migrate プラグインで警告されます。
リストに戻るSerialize
Breaking change: jQuery.param() はもはや %20 をプラス記号に変換しない
jQuery.ajax()
が POST するような form では、
application/x-www-form-urlencoded エンコードの仕様に
全ての空白は+
に変換されるべきと書かれています。
以前は、jQuery.param()
で変換してこれを実装していました。
今では、この変換はjQuery.ajax()
に移動しています。
jQuery.param()
でエンコードされたデータは空白を%20
に変換します。
これはネイティブの JavaScript のencodeURIComponent()
や
decodeURIComponent()
と互換性を持つようになります。
https://github.com/jquery/jquery/issues/2658
リストに戻るTraversing
Breaking change: .andSelf()
は削除された、.addBack()
を使いましょう
.addBack()
の方が、
処理内容と追加内容をフィルタするセレクタをオプションとして引数にとることを
よく表しているので、
.addBack()
の方を選択して.andSelf()
は jQuery 1.8 で廃止予定になり、3.0 で
削除されました。
※Migrate プラグインで警告されます。
リストに戻る