もちろん、そうでない方にも親しんで頂きたいと思います。

最近この記事が話題のようです。

この記事中にjQuery 1.6/1.6.1での .attr()仕様変更がらみの話で、うちの「jQuery1.6のattr()で困ったら、1.6.1にすればいいみたい。」の記事へリンクされていました。

ただこの記事はちょっと中身が細かくて、ぱぱっと理解するのは難しいんじゃないかなあと思って、この記事を書いています。どこまでご理解頂けるかはわかりませんが、あっちの記事よりは読みやすいはず。

今さら感もないではないですが……。(´ω`)

jQuery 1.6/1.6.1で何があったの?

  • .attr()にまとめていた処理を .attr().prop()に分割した
  • そしたら今まで動いていたものが動かなくなったので、大丈夫なように修正した

今まで .attr()だけで済んでいた処理を、バージョン1.6の更新で .attr().prop()に分割しました。そのまま動くコードもあれば動かないコードもあります。大混乱でした。

あまりに混乱が大きいので、結局次のバージョン1.6.1では再び .attr()で今まで通りの動きをするように戻す修正が行われる事となりました。

なんで .attr().prop()を分けたの?

  • もともと別物であるべきだった
  • 一緒に扱おうとして、バグが多くなってしまっていた

これはjQuery開発者の都合です。

もともとJavaScriptとしては、 .attr()的なものと .prop()的なものは別物です。別物だったのですが、jQueryではその違いを隠して、同じに扱えるようにしていました。

ところが元々違うものを同じように扱うという事に無理があり、最近はそのあたりの処理にバグが多くなってきてしまいました。そこで、バージョン1.6で思い切って分割して、シンプルにしてしまおう!という考えになったようです。(詳細追ってないので間違ってるかもしれません。)

しかし「今までのものが動かない」つまり互換性がないという事で、多くの混乱をもたらす結果となりました。そこで過度的な措置として .attr()の処理を修正し、今までコードのままでも動くようにしたのが、バージョン1.6.1です。(といっても、これもまた不完全だったりするようですが……。)

.attr().prop()は何が違うの?

  • .attr()はHTMLの属性を扱う
  • .prop()はJavaScriptプロパティを扱う
  • 両者には同じ名前で違うものがある(まぎらわしい!)

この二つのメソッドは扱う情報が違います。 .attr()HTMLの属性(attribute)を、 .prop()JavaScriptのプロパティ(property)を扱うためのメソッドです。

ここで混乱しがちなのが、属性とプロパティで「同じようだけど違うもの」があるという事です。

顕著な例はリンク先URLの扱いです。こんなHTMLがあったとします。

<a id="to_comments" href="#comments">コメント一覧</a>

何の事はない、ページ内ジャンプのリンクです。このリンクのリンク先URLは、 .attr().prop()のどちらでも取得できる(!)のですが、結果が異なってきます。

var $link = $('#to_comments');
alert($link.attr('href'));  // href属性の値を表示
alert($link.prop('href'));  // hrefプロパティの値を表示

さて、何が表示されるでしょうか?

  • .attr()#to_comment
  • .prop()http://example.com/path/to/page#to_comment

なんか全然違う……! Σ(°д°;)

実は「属性」として得られるものは、あくまでHTMLとして記述した「属性」の内容です。もちろんあなたがhref="http://…"と書いていれば、その通りに取得できます。

一方「プロパティ」というのは、JavaScriptが扱うための情報です。この情報はHTMLに記述された内容と常に一致するとは限りません。

もうひとつ、顕著な例を挙げます。チェックボックスのcheckedについてです。

<checkbox id="private" type="checkbox" checked />

チェックボックスです。チェックが付いていますね。このcheckedの値を確認します。

var $checkbox = $('#private');
alert($checkbox.attr('checked'));  // checked属性の値を表示
alert($checkbox.prop('checked'));  // checkedプロパティの値を表示

さて、何が表示されるでしょうか?

  • .attr()"checked"
  • .prop()true

ま、また全然違うものが……。

さらに、画面のチェックボックスをクリックしてチェックを外します。

  • .attr()"checked"
  • .prop()false

.attr()の方は変わっていませんね……。チェックされているかどうかという判定には .prop()を使う必要があります。

いかがでしょう、予想できましたか。

※なおchecked属性の値が何故checkedという文字列になるか、という話はHTMLの話になるので割愛します。ごく簡単に言うと、checkedselectedといった値のない属性の値は、属性の名前と同じになります。

.attr().prop()の使い分けってどうやって見分けよう?

まあ勘ですよね……。JavaScriptに明るくなれば大して悩まなくなるとは思います。

ざっくり言うと、HTMLに書いた属性の値を扱いたいときは .attr()を、いかにもJavaScript的な事をする時は .prop()を、でしょうか。

もっと詳しく

過去の記事の方が詳しいので、興味ある方はどうぞ。

だいぶ内容が細かい感じですが、 .attr().prop()のどちらをつかうべきかの一覧表なんかもあるので、そこだけでもチラ見しておくと役立つ事があるかもしれません。