jQuery 1.6.0 での変更箇所の自分なりのまとめ

リリースノートの jQuery Blog ≫ jQuery 1.6 Released を読んで、自分なりにまとめました。誤訳ももちろんあると思うので、 読まれる際はご注意を。(※このページをそのまま訳したわけではありません)
箇条書きにすると以下のような感じ:

  • .data()でのdata- 属性の取り込み方の変更
  • DOM の属性とプロパティの区別(.prop(), .removeProp()の導入と.attr() の変更)
  • 真偽値を取る属性の追加・削除
  • .attr().val()の拡張
  • jQuery.map()の対象範囲拡大
  • .css()の値の相対指定
  • .data()の性能向上
  • deferred.always(), deferred.pipe()の導入
  • アニメーションの同期
  • アニメーションがより滑らかに
  • .promise()の導入
  • イベントのトリガーの性能向上
  • jQuery.holdReady()の導入
  • :focusセレクタの導入
  • .find(), .closest(), .is()の改良(.nextUntil(), .parentsUntil(), .prevUntil() も)
  • .undelegate()の引数形式の追加

.data()でのdata- 属性の取り込み方の変更

jQuery 1.5 では、.data()を使って要素の全ての data- 属性の値を JSON の文法で JavaScript の値に変換して取り込めるようになりました。

1.6 ではdata- 属性を取り込む時のキーの値を HTML5 の仕様に合わせて、 ダッシュ(-)が入るdata- 属性はキャメルケース化するようになりました。 例えば 1.5.2 では、data-max-value="15"という属性は { max-value: 15 }という data オブジェクトが 作成されましたが、1.6 以降は{ maxValue: 15 }という data オブジェクトが作成されます。

そのため 1.6 に移行する場合はここら辺のコードを 変更する必要があるかもしれません。

DOM の属性とプロパティの区別(.prop(), .removeProp()の導入と.attr() の変更

※この変更はjQuery 1.6.1 で修正されて後方互換性を 保つようになりました。

jQuery 1.6 で DOM の属性への処理とプロパティへの処理を 分離し、それぞれ.attr().prop()(新規導入)に割り当てられました。 あわせて.removeProp()も新規導入されました。

.prop()は DOM 要素のプロパティを設定・取得し、 .removeProp()は DOM 要素のプロパティを削除します。

一般に DOM 属性は、マークアップ

<input type="text" value="abc">

における属性値のように、文書から読みこんだ DOM の状態を表します。 一方、 DOM のプロパティは文書の動的な状態を表します。例えば、 上の input 要素をクリックして abc に続いて def と入力した場合、 input 要素の value プロパティは"abcdef"ですが、value 属性の値は "abc"のままです。

だからといって DOM 属性は静的な値であるとは言えません。 うまくない例ですが class 属性などは className(IE だと class )プロパティの値を変更すると class 属性値も変更した値になります。また、 class 属性値を変更すると className プロパティの値も変わります。 属性とプロパティの値が連動しています。

DOM 属性は value 属性のように静的な値を持ったり、 class 属性のように動的な状態を持ったりします。そして たいていの場合、ブラウザは DOM 属性値を DOM プロパティの 初期値に使用します。

連動するタイプの DOM 属性なら.attr()でも .prop()でも問題はあまり無いのですが(それでも プロパティはあるが属性は無い場合などの問題もありますが) 問題は DOM 属性が静的な値の場合で、boolean 型の属性の場合です。

boolean 型の属性も静的な値を持ち、プロパティと連動しません。 例えば、

<input type="checkbox" checked>

というマークアップを考えてみます。この時、 DOM 属性 checked の値は空文字列("")です。一方、 DOM プロパティ checked の値はtrueです。また、

<input type="checkbox" checked="checked">

というマークアップの場合は、DOM 属性 checked の値は "checked"です。一方、 DOM プロパティ checked の値はこの場合もtrueです。そして、

<input type="checkbox">

のように DOM 属性 checked をマークアップしていない場合は、 DOM 属性 checked の値はnullです(原文では undefined)。一方、 DOM プロパティ checked の値はfalseになります。

要するに、属性 checked は存在するだけで、 たとえその属性が値を持っていなくとも、 DOM の checked プロパティはtrueになります。 そして、checked 属性は boolean 型の属性なのでプロパティと 連動しません。つまり、チェックボックスをクリックして チェックボックスの状態を変えても checked 属性の値は 変わりません。

1.6 より前では、.attr("checked") は checked プロパティの値を返していたのですが 1.6 で 属性とプロパティの処理を .attr() と .prop() に分離したことで .attr("checked") は属性の値を返すようになりました。 これが後方互換性の問題を引き起こし、 コードを修正する必要を発生させました。

1.6 に移行する場合は boolean 型の属性へのアクセスには .attr() の代わりに .prop() を使って(もしくは直接) プロパティにアクセスするように書き換えなければなりません。 checked 属性に限って言えば .is(":checked") なら 1.6 でも ちゃんと動きます。

と長々書きましたが、色々批判されたみたいで この変更はjQuery 1.6.1 で修正されて後方互換性を 保つようになりました。

真偽値を取る属性の追加・削除

selected や checked などの boolean 型の属性の追加・削除を、 .attr()truefalseを 渡すことで行えるようになりました。

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
$("#checkbox").attr("checked", true); // Checks it
$("#checkbox").attr("checked", false); // Unchecks it

もっとも、上に書いた理由により、DOM プロパティではなく DOM 属性に対してのみ処理するので、使い物になりません。 1.6.1 からは DOM プロパティに対しても処理するようになります。

.attr().val()の拡張

jQuery.cssHooksと同じような感じで .attr().val()を拡張できる、 jQuery.attrHooksjQuery.valHooksが追加されました。

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
jQuery.attrHooks.selected = {
  set: function( elem, value ) {
    if ( value === false ) {
      jQuery.removeAttr(elem, “selected”);
      return value;
    }
  }
};

jQuery.attrHooksjQuery.valHooksはドキュメント化されてないし、 jQuery 本体でも利用しているので、使うときは慎重になった方が いいかもしれません。

jQuery.map()の対象範囲拡大

jQuery.map()に JavaScript オブジェクトも 渡せるようになりました。

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
var counts = { first: 1, second: 2 };

counts = jQuery.map( counts, function( value ) {
  return value++;
});

.css()の値の相対指定

.animate()から機能を移植したそうで、 .css()に相対値("+=""-="を付けた値)を 指定できるようになりました。

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
// Move an item 10px over
$("#item").css("left", "+=10px");

らしいんですけど、試したところ動きません。 このバグは 1.6.2 で修正されたようです。 1.6.2 から使うようにしましょう。

.data()の性能向上

イベントのトリガー方法の改良に伴なって.data()の 性能が向上したそうです。どのくらい向上したかは該当ページを ご覧下さい。

deferred.always(), deferred.pipe()の導入

1.5 では Deferred オブジェクトが resolved, rejected どちらの 状態になっても同じ処理を行うようにしたい場合、例えば

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
function callback() {
    // deferred が resolved か rejected になった時の処理
}

defer.then( callback, callback );

のように.then()に同じ関数を2回渡すなどを していましたが、.always()が導入されて 1回で済むようになりました。

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
defer.always(function() {
    // deferred が resolved か rejected になった時の処理
});

そして、.pipe()が導入されました。 .pipe()は、非同期なタスクをつなげて実行したり、 登録したコールバック関数に渡す引数をフィルタリングしたりできる ユーティリティメソッドです。例えば、

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
function chainedAjax( url ) {
    return $.Deferred(function( defer ) {
        $.ajax( url ).then( function( url2 ) {
            $.ajax( url2 ).then( defer.resolve, defer.reject )
        }, defer.reject );
    }).promise();
}

のようなチェーンされたタスクを.pipe()なら 以下のように読みやすくできます。

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
function chainedAjax( url ) {
    return $.ajax( url ).pipe(function( url2 ) {
        return $.ajax( url2 );
    });
}

また、resolve() や reject() で指定したコールバックに渡す値を フィルタリングすることも出来ます。

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
var request = $.ajax( url ).pipe(function( data ) {
   return data.value;
});

request.done(function( value ) {
    // 元々のレスポンスの value プロパティの値だけ渡される
});

アニメーションの同期

複数のアニメーションが同期できるように改良したそうです。 具体的には、同時期に.animate()で 設定されたアニメーションは、その開始時刻を共通の値にして、 アニメーション中はフレームごとの処理(タイマーに登録された step()群)でアニメーションの終了タイミングなどを 判断するために取得する現在時刻を共通の値にしたようです。 以前は時刻の取得をアニメーションごとに行っていたので、 取得した時刻がわずかにずれる可能性がありました。

アニメーションがより滑らかに

※この変更はブラウザ側にバグがあるため jQuery 1.6.3 で一時的に削除されました。

ブラウザが導入した requestAnimationFrameというメソッドを 利用するようにしてアニメーションをより滑らかにしたそうです。

.promise()の導入

1.5 の$.ajax()のように、アニメーションの 完了を監視する Promise オブジェクトを返す .promise()が導入されました。 .promise()を実行すると、その jQuery オブジェクトが 保持する要素に登録されているアニメーションが全て終了するのを 監視する Promise オブジェクトが返されます。

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
$(".elements").fadeOut();

$.when( $(".elements") ).done(function( elements ) {
    // all elements faded out
});
// ※ $.when() 内部で .promise() が呼ばれ返されています。

イベントのトリガーの性能向上

.data()の性能向上のところで書いたように イベントのトリガーの性能が向上しました。

jQuery.holdReady()の導入

主にプラグイン開発者向けです。 1.5 で導入されたjQuery.readyWaitを 簡単に扱うことが出来ます。

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
jQuery.holdReady( true ); // ready イベントの実行を止める
// 後で、、、
jQuery.holdReady( false ); // 実行を再開する

:focusセレクタの導入

フォームの input 要素などの、現在ページ上で フォーカスされている要素を見つけるのに使えます。

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
$("input:focus").addClass("active");

.find(), .closest(), .is()の改良(.nextUntil(), .parentsUntil(), .prevUntil() も)

表題のメソッドに DOM 要素もしくは jQuery オブジェクトを 引数として渡すことができるようになりました。

// http://blog.jquery.com/2011/05/03/jquery-16-released/ での例です
// div の中にある .test な要素だけを返します
$("div").find( $(".test") )

.undelegate()の引数形式の追加

.undelegate( namespace )という用法が追加されました。

スポンサードリンク