jQuery1.9がリリースされました。
以前から告知されているとおりいくつかのメソッドの廃止や仕様変更などがあり、従来の記述方法では問題が起きる可能性もあるようです。おそらく動かなくなるプラグインも多く出てくるのではないかと思います。
そこで事前に問題点などを把握できるように、以前のバージョンのjQueryを使っていてバージョンアップを考えている方向けにjQuery Core 1.9 Upgrade Guideというアップグレード時の注意や新バージョンの仕様についてのドキュメントが用意されています。
私も新しいjQueryの使用を検討している一人なので、英語が得意というわけでもないのですががんばって読んで簡単ではありますが解説としてまとめました(完全な翻訳ではなく、概要を自分なりにまとめたものです)。まとめたのは Changes of Note in jQuery 1.9 という章になります。
分かりにくい部分については実際にコードを書いて試してみましたので、よろしければ参考にしてみてください。
————————————————————————————————————————————————
ADs
以下のようなクリックごとに処理を繰り返すtoggle(func(),func())が廃止されました。
なお、表示非表示を繰り返すtoggle();は使えます。
1 2 3 4 5 6 7 |
$('div').toggle( function(){ //1回目のクリックしたときの処理 },function(){ //2回目のクリックしたときの処理 } ); |
jQuery1.3より長らく非推奨とされてきたjQuery.browser()がとうとう廃止されました。
今後はjQuery.supportを使うかModernizrの使用が推奨されています。
live()は廃止され、on()を使用することになります。
記述は以下のようになります(documentに対してイベントをバインドすることに注意)
1 2 3 |
$(document).on("click",'a',function(){ //クリック時の処理 }); |
live()と同様に、die()が廃止されてoff()を使用することになります。
記述は以下のようになります。
1 |
$(document).off("click",'a'); |
廃止となりました(使ったことないけど・・・)。
このメソッドにより、元のメソッドに影響を与えることなく、”jQuery”のメソッドを安全に変更が可能になったり、jQueryプラグインのためのカプセル化と名前空間を利用できるようになります。
$.sub() | Qrefy – jQuery日本語リファレンス
生成した要素にadd()でドキュメント上に存在している要素を追加した場合、並び順が「存在している要素→生成した要素」の順にソートされるようになりました。
言葉で書くと分かりにくいですが、実際の実行例を見るとjQuery1.9と1.8で結果が異なっているのが分かります。
2013.01.31修正
真逆になってました。1.9で推奨されているのはaddBack()です。
コメントでのご指摘ありがとうございます。
andSelf()というメソッドがaddBack()という名称に変更されました。
andSelf()については以下の解説が分かりやすいです。
こちらは、直前に選択していた要素を今の要素に付け加えて、新しく要素を選択し直します。 .end()は、1歩前に戻りますが、.andSelf()は、更に前進していくイメージです。
jQuery入門道場 ~ jQueryの使い方~ 【横断2(Traversing)】
ある要素に対してafter()やbefore()を行った際、その要素にafter()/before()で追加された要素が含まれなくなりました。
1 2 |
var obj = $('<p class="generate">生成されるp(after)</p>').after($('div.block')); //このobjは<p class="generate">生成されるp(after)</p>であり、<p class="generate">生成されるp(after)</p><div class="block">hogehoge</div>ではない |
jQuery1.9でのafter()/before()の挙動
jQuery1.8でのafter()/before()の挙動
※これは1.9からの変更点ではないように思います。
.appendTo, .insertBefore, .insertAfter,.replaceAllといったメソッドは返り値として処理後のオブジェクトを返すはずなのですが、特定のバージョンで処理前のオブジェクトが返っていたようです。
1 2 3 4 |
$(function(){ var obj = $('<p>あああああ</p>').appendTo('hoge'); //hogeなんてタグはない //objはfalseが帰るはずなのにpが返る・・・らしい }); |
Ticket #11230のことではないかと・・・。
ajaxStart, ajaxStop, ajaxSend, ajaxComplete, ajaxError, ajaxSuccessのイベントはdocumentにバインドしないといけないようになりました。
具体的な記述は以下のようになります。
1 2 |
$(document).ajaxStart(function(){ $("#status").text("Ajax started"); }); //id="status"というタグ内に「Ajax started」というメッセージが挿入されます。 |
チェックボックスやラジオボタンにclick()やtrigger(‘click’)でクリックを実行した際、1.9では
・クリックする
・チェックが入る/外す
を違う処理として厳密に区別するようになりました。
e.preventDefault();でイベント伝達をキャンセルした場合に分かりやすいですが、1.9ではクリックではない「チェックを入れる/外す」というイベントに影響は与えないためチェックの状態が変わります。
非常に分かりにくいので実際のコードを見てみると分かりやすいです。
jQuery1.9でチェックボックスに対するclick()の挙動
※チェックが入っているのにsize()でのカウントが0である点に注目
jQuery1.8でチェックボックスに対するclick()の挙動
クリックされることとチェックが入ることはイコールではないということでしょうか。
○○という処理を行なっているのは何と言うイベントか、ということを意識する必要があるでしょう。
通常ブラウザのfocusやblurイベントは
1.まずblurイベントが発火
2.次にfocusイベントが発火
という順序になりますが、jQuery1.8以前はfocus→blurの順でイベントが発火していました。
1.9からはブラウザと同じくblur→focusの順で発火するようになったようです。
※その影響かは分からないけど1.9だと$(document).readyでフォームにフォーカスさせるみたいなことができなくなってない?→参考
1.8以前では$(…)内の文字列はHTMLタグと解釈されていましたが、閲覧者により不正なコードを埋め込まれる危険性を秘めています(要するにXSSのこと)。
1.9より$(…)内の文字列は「<」から始まる場合に限りHTMLタグであるとみなし、処理を実行します。
XSS対策にはparseHTML()メソッドを使い無害化することができます。
2013.01.25追記
「無害化」という解釈について多数ご指摘をいただきましたので、当セクションについては他のブログの解説や原文をご参照ください。
勉強になりました。ありがとうございました。
jQuery 1.9 の $.parseHTML とかその辺
$.parseHTML Sample に書いたように,イベントハンドラは実行できるので単純に $(String) を $($.parseHTML(String)) に置き換えただけでは,事態は何も改善しませんしむしろ悪化することもあります.無害化というような効果はありません.
data()メソッドにドット(「.」)を含む値を指定した際、ドットも含めて一意の文字列として値を取得します。
.data(“abc.def”)のようなメソッドは「abc.def」というdata属性が取得されます。
jQueryの過去のバージョンでは、メソッドを通した場合はドキュメント上の順序にソートした新たな要素の配列として返されます。一部の例外として、.parents()メソッドはドキュメントの逆にソートされます(子要素→親要素)。
しかしドキュメント上に存在しない要素(createElementされた要素)が含まれた場合はこの順序になりません。
1.9ではまずドキュメント上の要素がソートされ、生成された要素はその後ろに配置されます。
※.add()で発生している順序の違いがこの内容にあたります。
DOM操作を行うメソッド($(),.append(),.wrap()など)はHTML内に挿入されるスクリプトが再度実行されないようにドキュメントから取り除きます。不正なコードによりスクリプトタグを挿入されても実行されることはありません。
新たにスクリプトをロードしたいときはjQuery.getScript()を使用します。
1.6で導入された.prop()はノードにプロパティを設定すると同時に属性値(.attr()で設定するもの)を設定します。
※.prop()と.attr()への分割は色々と議論と混乱を呼びました。
CSSは分かるけどjQueryは苦手……という人が .attr()と .prop()に親しんでくれるといいなーと思って書きました。 | Ginpen.com
1.9までは.attr()メソッドをサポートしますが、将来属性とプロパティを混同した動作は混乱を引き起こします。
例えばチェックボックスのオン・オフを切り替えるような処理を考えてみると、input[:checked]でマッチする要素は属性値が「checked=”checked"」ではなく、checkedプロパティがtrueであるものにマッチすべきです。
1 2 3 4 |
$(elem).attr("checked", "checked"); // 属性を変更したいのなら正しい指定 $(elem).prop("checked", true); // チェックボックスにチェックを入れたいなら正しい指定 $(elem).removeAttr("checked"); // 属性(checked)を削除したいなら正しい $(elem).prop("checked", false); // チェックを外したいなら正しい |
フォームのvalue属性はプロパティと属性の曖昧さを示すもう一つの例です。属性は一般的にHTMLから読み込まれた値を反映し、プロパティは現在の値を反映します。.val()メソッドはjQueryが推奨するvalue値を取得する方法ですので、このような混乱はユーザーに影響を与えません。
しかしinput[value=”abc”]のようなセレクタで取得する方法は属性値を取得しますがプロパティを取得するものではありません。これはjQuery1.9の正常で一貫性のある動作です。
※まとめると.attr()と.prop()、属性とプロパティは違うものなのできちんと区別して使いましょう。ということでしょう。
1.8以前ではinputやbutton要素に対してtypeを設定しようとした場合、IE6/7/8でJavascriptエラーが発生します。
しかし1.9ではこのエラーを無視するようにしました。ですが内部的にはエラーが発生しているので注意してください(警告メッセージが出ないので分かりにくい)。
2013.01.22修正
jQuery 1.9.0におけるhover()(to-R様より)
イベント「hover」が非推奨となりました。具体的には以下の様なコードが非推奨となります。
1 2 3 |
$(".hoge").on("hover",function(){ //do something }); |
※以下の様な記述が非推奨となるものだと思ってましたが間違いでした。.hover(function(){},function(){})は使用可能です。
1 2 3 4 5 6 7 8 |
$('.hoge').hover( function(){ //マウスオーバー時の処理 }, function(){ //マウスアウト時の処理 } ); |
.selectorプロパティは非推奨となりました。
※.live()がこのプロパティを使っているが.live()自体が非推奨となったので同様に非推奨となるようです。
attr()メソッドには.attr(elem, name, value, pass)と4つの引数を持つことができますが、pass引数が削除されました。
※ドキュメント化されていない引数です。
AjaxでJSON(JSONP)を取得する際に、成功している(successやpromiseが返る)のに空のデータしか取れないことがあります。そのような場合は不正なJSONデータであると判断し、エラーを返すようにしました。
ここだけはどうしても分かりませんでした・・・。proxy()の何がtrue/falseを返すのか分かりません。
2013.01.18追記
kjirou様よりコメントをいただきました。ありがとうございます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var f = function(){ return this === window } // 1.9.0の場合 ($.proxy(f, false)()) // -> true (thisはwindowオブジェクト) ($.proxy(f, 0)()) // -> true (thisはwindowオブジェクト) // 1.8.0の場合 ($.proxy(f, false)()) // -> false (thisはundefined) ($.proxy(f, 0)()) // -> false (thisはNumberオブジェクト) // 1.9.0と1.8.3で共通 ($.proxy(f)()) // -> true ($.proxy(f, null)()) // -> true ($.proxy(f, undefined)()) // -> true ($.proxy(f, '')()) // -> Error |
falsyな値が第二引数に入った場合の this が
一部の場合についてのみ変わったようです個人的には、旧来の0をNumberにする方が正しい気もしますが、
いずれにせよ、オブジェクト以外はcontext入れるな!ということだと思われます
jQueryのコードを見てみると、proxy()メソッドの第二引数がfalseの場合、thisが代入されます。具体的なjQuery内のコードは以下のようになっています。
1 2 3 4 |
args = core_slice.call( arguments, 2 ); proxy = function() { return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); }; |
1.8以前は第二引数(context)がそのまま代入されたため、前述の結果となります。
1.7以前のバージョンでは以下の様なコードでオブジェクトにバインドされたイベントを取得することができます。
※1.8では既に使えなくなっていた。
1 |
var clickEvent = $('.hoge').data('events').click; |
1.9で上記のメソッド(data(‘events’))は削除されましたがMigrateプラグインで使用することが可能です。
イベントオブジェクトのプロパティであるattrChange, attrName, relatedNode,srcElementは非クロスブラウザのプロパティであるため、1.7より非推奨の要素となっています。
1.9ではイベントハンドラに渡されるイベントオブジェクトにコピーされなくなりました。
ドキュメント化されていないメソッドの引数についての仕様が変更されたり廃止されたりしています。
Migrateプラグインでもサポートされる予定はありません。
以前よりドキュメント化されていませんでしたが、以下のメソッドは1.9で廃止されました。
jQuery.deletedIds
jQuery.uuid
jQuery.attrFn
jQuery.clean()
jQuery.event.handle()
jQuery.offset.bodyOffset()
ADs
訳文ありがとうございます、とても助かりました
jQuery.proxyについて、英文は訳せませんでしたが
挙動の差については確認しました
—-
var f = function(){ return this === window }
// 1.9.0の場合
($.proxy(f, false)()) // -> true (thisはwindowオブジェクト)
($.proxy(f, 0)()) // -> true (thisはwindowオブジェクト)
// 1.8.0の場合
($.proxy(f, false)()) // -> false (thisはundefined)
($.proxy(f, 0)()) // -> false (thisはNumberオブジェクト)
// 1.9.0と1.8.3で共通
($.proxy(f)()) // -> true
($.proxy(f, null)()) // -> true
($.proxy(f, undefined)()) // -> true
($.proxy(f, ”)()) // -> Error
—-
falsyな値が第二引数に入った場合の this が
一部の場合についてのみ変わったようです
個人的には、旧来の0をNumberにする方が正しい気もしますが、
いずれにせよ、オブジェクト以外はcontext入れるな!ということだと思われます
kjirou様
コメントありがとうございます。
proxy()メソッドを使ったことがなかったのでうまく解読することができませんでした。ありがとうございます。
本文中にも追記させていただきました。
「.addBack( selector ) の名称変更( .andSelf()に」じゃなくて、.andSelf()が.addBack( selector )に変わったんじゃないですか。
タツオ様
ご指摘ありがとうございます。誤訳申し訳ございません。
記事中の記述を修正いたしました。
「スクリプトのロードと実行について」ですが
「HTML内に挿入されるスクリプトが再度実行されないようにドキュメントから取り除きます」というのは、1.9より前のバージョンでの動作じゃないですか?
1.9からは削除されずに、内部的に実行済みのチェックが付けられるように変わったのだと思います。
「$(“input”).attr(“type”, newValue) in oldIE」
ですが、エラーを無視しているわけでなく、
IE6/7/8では、一度、生成したinput要素のtype属性を変更することができなかったので、それに合わせてjQuery1.8以前ではエラーをスローするという仕様にしてあったものが、1.9からは、ブラウザが許せば変更することが可能になったということだとおもいます。