WWW Watch

jQuery Core 1.9 アップグレードガイド 日本語訳

jQuery 1.9 の正式版、および jQuery 2.0 のベータ版がリリースされましたが、これに際して公開された、jQuery 1.9 への移行ガイド 「jQuery Core 1.9 Upgrade Guide」 を翻訳してみたので公開してみます。

ちょっと話題としては乗り遅れた感が漂いますが、先月末に jQuery 1.9 の正式版、および jQuery 2.0 のベータ版がリリースされました。

これに際して公開された、jQuery 1.9 への移行ガイド 「jQuery Core 1.9 Upgrade Guide」 を翻訳してみたので下記に公開してみます。

jQuery 1.9 / 2.0 とは?

jQuery 2.0 は IE 6/7/8 への対応をやめることで、より軽量で高速、そして安定化を目指した jQuery のメジャーバージョンアップ版ですが、jQuery 1.9 は 2.0 と 完全な互換性を持ちつつも、レガシーブラウザへの対応が可能なバージョンで、IE 8 以前のサポートが必要な環境では最新の jQuery として使用可能です。

逆に IE 8 以前とか知らないとか、スマートフォンのみを対象とした Web サイト、Web アプリケーションであれば、2.0 を使用することでより軽量で、高速な処理が可能になります。つまり、1.9 を使うか、2.0 を使うかはサポートしたいブラウザによって選択すればよく、機能としては全く同じということです。

で、1.9 のリリースにあたり、以前のバージョンからあまり使われていなかったり、問題があるとされていた機能が整理されたり、修正されたりしています。このため、1.8 以前から 1.9 にバージョンアップする場合、プラグインや Web サイトの機能に互換性の問題が発生する可能性があり、今回翻訳した 「jQuery Core 1.9 Upgrade Guide」 では、その 1.9 における変更点や、どういう風に対処したらいいかを簡単にまとめたもので、jQuery 1.9 への移行を検討する際に役に立つと思います。

なお、今回は単純に書いてあることを翻訳しただけですので、個々の細かい解説などは他の JavaScript 界隈の Blog さんなどを見てください。ちょっと言い回しがわかりにくい点があったんですが、その辺はなるべく原文に近い感じでやってみたのですが、個人的にも理解度が足りなくて補足できていない点もあるので、ツッコミもらえれば補足していきます。後半は集中力が切れた……

でははじめましょう。


原文

目次 (クリックで各項目に移動します)

概要

jQuery 1.9 は、動作に一貫性がなく非効率的だったいくつかの API を削除または修正するものです。ここで挙げる変更のほとんどは、jQuery の以前のバージョン、とりわけ 1.7 や 1.8 のころから廃止されることが予示されていたものです。

これら変更におけるチームの目標は、jQuery の一貫性を損なっていたり使いにくくしていた動作の修正であり、また、その過程でファイルサイズと全体的なパフォーマンスの両方を改善することでした。

このリストは一見嫌な予感をさせるかもしれません。しかし変更のほとんどは、特殊な状況とエッジケースに対するものですし、そのいくつかは、問題のある jQuery の動作として、古くより多くの要望が寄せられていた変更です。最初のステップとして、あなたのコードが機能するかを確認する最善の方法は、以下に説明する通り、jQuery 1.9 と 移行プラグインの両方で確認してみることです。

現時点で本ガイドは、標準の jQuery API ドキュメントに対する付録という位置づけで、1.9 の動作について解説されていない場合もあります。jQuery API Documentation の各ページに、1.9 の変更点が反映されるまでしばらくお待ちください。

jQuery Migrate プラグイン

我々は、既存サイトやプラグインが今回の変更の影響を受ける可能性について認識し、アップデート過渡期のため、「jQuery Migrate プラグイン (jQuery 移行プラグイン)」 を用意しました。1.9 で変更された動作が、jQuery Migrate プラグインにより復元できるかは、以下に記載された個々の説明で示しています。jQuery 2.0 には jQuery 1.9 における変更点のすべてが適用されますが、また同時に、jQuery Migrate プラグインも利用できることは覚えておいてください。

圧縮されていない jQuery Migrate プラグインの開発版は、コンソールへのログ出力が可能で、特定の非推奨、または削除済みの機能が使われると警告を発するようになっています。この機能は、既存の jQuery コードとプラグインの問題を発見し、改修して移行するためのデバッグツールとしてとても便利です。1.6.4 以降の jQuery コアバージョンに対する診断ツールとして利用できます。

圧縮版のプラグインはログを出力しませんし、1.9 以上に移行することが望ましいですが、古い、互換性のないコードやプラグインも使わなくてはならない Web サイトでは利用することができます。こちらを使用する場合、あくまで短期間の問題解決手段としてのみの使用が好しいですが、あとはご自身で判断してください。

なお、jQuery Migrate プラグインについてはこちらを参照してください。

jQuery 1.9 での変更点

以下のリストは jQuery 1.9 で加えられたすべての変更点を示すものではありません。既存のソースコードの動作に影響を与えると予想される変更点だけをまとめています。すべての変更点やその詳細については、jQuery blog での変更履歴や bugs.jquery.com を確認してください。

.toggle(function, function, ... ) の削除

ここでいう .toggle() は 「要素がクリックされる毎に関数を実行する」 .toggle() のことです。「要素の表示 / 非表示を切り替える」 .toggle() と混同しないでください。後者の .toggle() は非推奨にはなっていません。前者は混乱を減らし、ライブラリのモジュール化を進める中で削除されました。jQuery Migrate プラグインでこの機能は復元できます。

jQuery.browser() の削除

jQuery.browser() メソッドは、jQuery 1.3 より非推奨になっていましたが、1.9 で削除されます。必要であれば、移行プラグインの機能の一部として利用可能ですが、Modernizr のような機能検出のためのライブラリを使用することを推奨します。

.live() の削除

.live() メソッドは、jQuery 1.7 より非推奨になっていましたが、1.9 で削除されます。我々は、代わりに .on() メソッドを使用して、コードをアップデートすることを推奨します。例えば、$("a.foo").live("click", fn) を置き換えるには、$(document).on("click", "a.foo", fn) のように記述します。

詳しい説明は .on() のドキュメント を参照してください。jQuery Migrate プラグインにより、.live() メソッドを復元することもできます。

.die() の削除

.die() メソッドは、jQuery 1.7 より非推奨になっていましたが、1.9 で削除されます。我々は、代わりに .off() メソッドを使用して、コードをアップデートすることを推奨します。例えば、$("a.foo").die("click") を置き換えるには、$(document).off("click", "a.foo") のように記述します。

詳しい説明は .off() のドキュメント を参照してください。jQuery Migrate プラグインにより、.die() メソッドを復元することもできます。

jQuery.sub() の削除

jQuery コアに残しておくに値するほど利用されなかったため、jQuery.sub() メソッドは、jQuery Migrate プラグインに移動されました。jQuery Migrate プラグインを使用することでこの機能は復元可能です。

.add()

.add() メソッドは、常にその結果をドキュメント順に返すようになりました。1.9 以前では、ノードセットの先頭に非接続ノード (つまりドキュメント上になく、新たに生成されたノード) がある場合、.add() はノードをドキュメント順にソートしませんでしたが、1.9 ではノードは常にドキュメント順に返され、非接続ノードは接続ノードの後ろに置かれます。

.andSelf() は .addBack( selector ) に置き換え

jQuery 1.8 では、「現在の要素セットに以前の要素セットを加える」 というこのメソッドの機能にふさわしい名称である .addBack() を推奨し、.andSelf() メソッドは非推奨とされました。

新しいメソッドは、セレクタを指定して現在の要素に追加する要素をフィルタリングすることもできます。つまり、$("section, aside").children("ul").addBack("aside") は、「すべての aside ノード」 に加え、「section 、および aside ノードの子となる ul 要素」 を文書順にしたセットとなります。

.andSelf() メソッドは jQuery 1.9 でも機能しますが、できるだけ早く名称を変更することをお勧めします。jQuery Migrate プラグインは .andSelf() が使用されると警告します。

.after()、.before()、.replaceWith() と非接続ノード

1.9 以前では、.after().before()、および .replaceWith() メソッドはセット内の最初のノードがドキュメントに接続していない場合、現在の jQuery セット内でノードを追加または変更しようとし、さらに元のセットではなく新しい jQuery セットを返していました。これにより、いくつかの不具合やバグが発生していました。つまり、このメソッドはその引数によっては、新しい結果を返したり、返さなかったりするのです!

1.9では、これらのメソッドは常に元々の変更されていないセットを返し、親がないノード上で .after().before()、または .replaceWith() を使用しても何も行いません。つまり、セットもノードも変更されることはありません。

.appendTo、.insertBefore、.insertAfter、.replaceAll

1.9 では、これらのメソッドは常に新しいセットを返すことで、メソッドチェーンや .end() メソッドにおいて使いやすくなりました。1.9 以前では、指定した要素が 1つの場合のみ、元のセットを返しました。

ここで覚えておきたいのは、これらのメソッドは常に、指定した要素に追加された全要素を保持しているということです。セレクタによって要素が何も指定されていない場合 (例えば $(elements).appendTo("#not_found"))、空のセットが返されます。

AJAX イベントは document に関連付けなけらばならない

jQuery 1.9 では、Global AJAX Events (ajaxStart、ajaxStop、ajaxSend、ajaxComplete、ajaxError、ajaxSuccess) は document 要素でのみトリガーされるようになりました。

AJAX イベントが document に登録されるよう、プログラムを書き換える必要があります。例えば、下記のようなソースコードは

$("#status").ajaxStart(function(){ $(this).text("Ajax started"); });

下記のように変更する必要があります。

$(document).ajaxStart(function(){ $("#status").text("Ajax started"); });

.trigger() された click イベント中のチェックボックス / ラジオボタンの状態

ユーザーがチェックボックス、またはラジオボタンをクリックするとき、イベントハンドラは event.preventDefault() がノード上で呼び出されない状態、つまり、更新された状態のノードとして扱われます。

例えば、ユーザーがチェックされていないチェックボックスをクリックした場合、イベントハンドラから見たチェックボックスは 「checked」 された状態になります。1.9 以前では、.trigger("click")、または .click() によってトリガーされたチェックボックスは、イベントでユーザーがクリックする前の状態として扱われていました。1.9 でこの問題は修正され、ユーザーの操作と同じ、チェックされた状態を反映するようになりました。

トリガーされた focus イベントの発生順序

ユーザーがフォーム要素をフォーカスするためにクリック、あるいはタブキーによって移動した時、ブラウザはまず、それまでフォーカスされた要素に対して blur イベントを発火し、それから新しい要素に対して focus イベントを発火します。

1.9 以前では、.trigger("focus")、または .focus() によって focus イベントをトリガーした場合、新しい要素に対して focus イベントを発火した後で、その要素にフォーカスする前にフォーカスしていた要素に対して blur イベントが発火していました。

1.9 では、この動作がユーザーが実際にフォーカスを変更する時と同様の順序を再現するように変更されています。

ネイティブ DOM の focus イベントでは、対象となる要素がまだフォーカスされておらず、かつフォーカスが可能な場合に、ブラウザは focus イベントハンドラを呼び出します。

jQuery では、たとえ要素がフォーカスすることができない場合でも、.trigger("focus")、または .focus() によるイベントハンドラが必ず実行されますが、jQuery 1.9 でもこの動作は引き続き変更ありません。これは、要素がすでにフォーカスされていたり、要素が 「disabled (フォーカスできない)」 状態ではイベントハンドラを実行しない DOM の .focus() メソッドとは異なる動作です。

残念なことに、 Internet Explorer (6 ~ 10) のすべてのバージョンは、focus イベントを 非同期的に発火します。IEで .trigger("focus") する際、 jQuery は後から実行される非同期的な focus イベントを 「検知」 できないため、先に述べた、focus イベントが常に実行される仕様に則った結果、イベントハンドラが 2回実行される場合があります。

この重複実行を避けるためには、DOM の .focus() メソッドを使用します (例えば、$("selector").get(0).focus())。ただし、この場合はイベントハンドラが全く実行されない危険があります。

jQuery(htmlString) 対 jQuery(selectorString)

1.9 以前では、文字列に HTML タグがある場合、その文字列は HTML 文字列であると見なされていましたが、これにより不正なコードを実行されたり、有効なセレクタ文字列が拒絶される可能性がありました。

1.9 では、"<" で始まる場合のみ、HTML であると見なされます。以前の動作を復元するには、Migrate プラグインを使用します。

HTML タグではない任意のテキストから始まる文字列を、HTML として扱いたい場合は、マークアップを表す DOM ノードの配列を返す jQuery.parseHTML() に文字列を渡してください。例えば :$($.parseHTML(htmlString)). とすることで jQuery オブジェクトを HTML 文字列から取得することができます。これは、HTML テンプレートを処理する場合などにベストプラクティスとなるでしょう。

$("<p>Testing</p>").appendTo("body") 等の文字列を単に扱う場合、この変更による影響はありません。

まとめ: "<" 以外で始まる HTML 文字列を jQuery() に渡した場合、それはセレクタとして解釈されますが、HTML 文字列は通常、セレクタとしては無効な文字列となるため、Sizzle セレクタエンジンによってエラーと判断されます。任意の HTML をパースするには、jQuery.parseHTML() を使用してください。

jQuery Migrate プラグインを使用した場合、$() に対して 「HTMLのような」 文字列を渡すと、従来の処理方法が適用されます。

.data() メソッドにおけるイベントの無効化とピリオドを含む値

1.9 では .data() からドキュメント化されておらず、かつ非効率な、設定した値を監視したり、値を取得するための仕組み (訳者注: getData / setData イベント?) が削除されましたが、この変更によって .data() メソッドがピリオドを含む値を取得可能になりました。

1.9 では、.data("abc.def") を指定した場合、"abc" ではなく abc.def" として取得します。ここで覚えておきたいのは、jQuery.data() メソッドはイベントをサポートしたことがないため、機能が変更されることはないということです。

なお、jQuery Migrate プラグインは旧バージョンの動作を復元しません。

jQuery セット内における非接続ノードの順序

多くのバージョンにおいて、新しいノードセットを返すほぼすべての jQuery メソッドはノードをドキュメント上の順序にソートします。(一部、ドキュメント上の順序とは逆の順序で返す .parents() 等のメソッドもありますが、そのような例外はすでにドキュメント化されていて、1.9 において変更されていません)

1.9 以前では、接続ノードと非接続ノードを両方含むセットは、非接続ノードが元のソートされていないセットの先頭にあるかどうかによってソートされたりされなかったりしました。

1.9 では、接続ノードは常にドキュメント上の順序の先頭に、非接続ノードはそれらの後に配置されます。

jQuery Migrate プラグインは旧動作を復元しません。

HTML コンテンツ内でのスクリプトの読み込みと実行

1.9 以前では、HTML を受け取るどのメソッド (例えば $().append().wrap()) も HTML 内のスクリプトを実行したら、それが再び実行されるのを防ぐためにそれらをドキュメントから取り除いていました。

しかし、スクリプトが取り除かれた後で、.wrap() 等のメソッドによってスクリプトが再びドキュメントに挿入された場合、それが再度実行されてしまいます。

1.9 では、ドキュメントに挿入されたスクリプトは実行さた後もそのままドキュメント内に残されますが、実行済みであるとマークされます。よって、取り除かれたスクリプトが再び挿入されたとしても、それが実行されることはありません。

この変更がされたからといって、実行可能な JavaScript を HTML マークアップに混在されることは、デザイン、セキュリティ、信頼性、パフォーマンスの面からもとても不適切な行いです。

例えば、HTML に含まれる外部 script タグは同期的に転送され解析されますが、それは非常に時間がかかる作業です。このようなスクリプトがいつロードするのか、またはロードされたのかを通知したり、エラーが生じた場合にそれに適切に対応するためのインターフェースはありません。

既存の script タグを複製してドキュメント内にロードするコードは、その script タグがすでに実行済みとしてマークされているため、動作しません。新しいスクリプトをロードするには、jQuery.getScript() を使用してください。

.attr() 対 .prop()

jQuery 1.6 は、ノードの値を設定したり、取得するのメソッドとして .prop() メソッドを導入し、値の設定に .attr() を使用することを非推奨としました。

しかし、1.9 までのバージョンは特定の条件下においては .attr() を引き続き使用可能にしました。しかし、この後方互換性のため、属性と値を区別するセレクタが使用される際に不具合が発生しました。

例えば、チェックボックスにおける checked や disabled 等の真偽値属性は、この変更によって影響を受けます。"input[checked]" の正しい動作は、その属性の値に関係なく、checked 属性のあるチェックボックスを選択することです。

一方、"input:checked" は、checked 属性の真偽値 (true / false)によって、「現在チェックされている」 チェックボックスを選択します。これは、例えばユーザーがチェックボックスをクリックする動作に影響を受けます。

1.9 以前のバージョンは、これらのセレクタで正しいノードを選択できない場合があります。

チェックボックスに対して checked 属性を与える例を以下に挙げます。同じことが disabled でも言えます。ここで覚えておきたいのは、全てのブラウザにおいて、チェックボックスの状態によって変更されるのは 「値 (プロパティ)」 だけだということです。属性を設定する必要は滅多にありません。

// 属性を変更したいのなら正しい指定
$(elem).attr("checked", "checked");
// チェックボックスにチェックを入れたいなら正しい指定
$(elem).prop("checked", true);
 
// 属性を削除したいなら正しい指定
$(elem).removeAttr("checked");
// チェックを外したいなら正しい指定
$(elem).prop("checked", false);

値と属性の曖昧さを示すもう 1つの例は、input 要素上の value 属性です。通常、属性は HTML マークアップから読まれた値を反映し、プロパティは現在の値を反映します。.val() メソッドは、フォーム要素の値を設定したり、取得する際に jQuery が推奨する方法なので、このような混乱をユーザーに与えません。

しかし、"input[value=abc]" のようなセレクタが使用される場合は、属性値が取得されるべきですし、例えばユーザーのテキスト入力等による値の変更に影響されません。jQuery 1.9 では、これは正しく、一貫して動作します。jQuery の旧バージョンでは、属性を使用しなければいけない時に値が使用されることがあります。

jQuery Migrate プラグインは、旧動作を復元します。

古い IE における $("input").attr("type", newValue)

1.9 より前のバージョンでは、jQuery は input 要素、または button 要素の type 属性を変更しようとするとエラーを返していました。これは、 IE 6/7/8 が input 要素の type 属性値の変更に対してエラーを返すため、これにあわせて行われた処置でした。

jQuery 1.9 では、ブラウザが許可する場合、要素の type 属性値を変更することができます。しかし、当然ながらこのようなコードは、古い IE でエラーになることを覚えておく必要があります。

jQuery Migrate プラグインは type 属性値の変更を行おうとすると警告しますが、JavaScript エラーは返しません。

"hover" 擬似イベント

1.9 では、"mouseenter mouseleave" の別名としての "hover" イベントはサポートされなくなりました。これにより、アプリケーションは独自の "hover" イベントをアタッチし、トリガーすることができます。既存のコードへの修正点を見つけて差し替えるのは簡単でしょう。また、"hover" 擬似イベントは、移行を容易にするため、jQuery Migrate プラグインにおいてもサポートされています。

jQuery オブジェクト上の .selector プロパティ

非推奨となった jQuery オブジェクト上の .selector プロパティに残された目的は、非推奨になった .live() イベントをサポートすることです。しかし、jQuery は、1.9 で .live() をサポートしませんので、jQuery オブジェクト上で .selector プロパティは使用しないでください。jQuery Migrate プラグインもこのプロパティを復元しません。

jQuery.attr()

1.9 では、ドキュメント化されていない jQuery.attr(elem, name, value, pass) のうち、pass 引数は削除されました。この引数に依存するコードは書き換える必要がありますが、jQuery Migrate プラグインで復元が可能であり、さらにこの引数が使用された場合は警告します。

jQuery.ajax が JSON の結果として空の文字列を返す

1.9 より前では、 JSON、または JSONP 型のデータを返すことが期待される ajax の呼び出しにおいて、空の文字列が返った場合でも、それを成功と見なし、 success ハンドラには null が渡されます。

1.9 では、空の文字列は不正な形式の JSON としてエラーを返します。error ハンドラが検知に使用されます。

jQuery.proxy() コンテキスト

1.9 で新しいことは、コンテキストに False な値が入る jQuery.proxy が返す関数には this オブジェクトが保存されることです。以前は、コンテキストに null / undefined といった Falsy な値が指定された場合は、グローバルオブジェクト (window) に置き換えられ、または 1つのオブジェクトにラップされていました (例: new Boolean(false))

.data("events")

1.9 より前では、「events」という名前でデータ要素を定義したコードが他にない場合、jQuery のドキュメント化されていない内部イベントデータの構造を .data("events") を使用して取得することができました。しかし、この機能は 1.9 で削除されます。これにより、内部イベントデータを取得するインターフェースなくなりました

jQuery Migrate プラグインはこの動作を復元します。

削除された Event オブジェクトのプロパティ

Event オブジェクトの attrChangeattrNamerelatedNode、および srcElement プロパティはクロスブラウザに動作しないため、jQuery 1.7 で非推奨となりましたが、jQuery 1.9 では、イベントハンドラに渡される Event オブジェクトにコピーされなくなりました。

これらのプロパティは、 jQuery のどのバージョンにおいても event の代わりに event.originalEvent を使用することでアクセス可能です。jQuery Migrate プラグインは、これらのプロパティを Event オブジェクトに戻すことができます。

API メソッドのドキュメント化されていない引数

1.9 以前では、複数の API メソッドにはドキュメント化されていない引数があり、それは偶発的な誤用、あるいは誤ったダックパンチング (モンキーパッチ) の可能性を引き起こしましたが、現在、これらの引数は削除されました。

影響を受けたメソッドには、jQuery.data()jQuery.removeData()jQuery.attr() があります。jQuery Migrate プラグインはこれらの引数をサポートしません。

その他のドキュメント化されていないプロパティやメソッド

下記のプロパティやメソッドはドキュメント化されてませんでしたが、1.9 で削除されました。これらを使用したソースコードは書き直す必要があります。

  • jQuery.deletedIds
  • jQuery.uuid
  • jQuery.attrFn
  • jQuery.clean()
  • jQuery.event.handle()
  • jQuery.offset.bodyOffset()

以上。

Recent Entry

全ての記事一覧を見る

Hot Entry

逆引きおすすめエントリー