jQueryのpropとattrの違いと使い分け

2014/10/27

まず、HTMLの基礎知識から

HTMLでcheckboxにchecked属性でチェックを入った状態にしたいときには、 値無しでchecked属性を付加すればOKです(1)。 HTMLではchecked属性値は省略可になっていますので、特に記述する必要はありません。

属性値のデフォルトは「"checked"」なのでつまり「checked="checked"」となります(2)。 しかし属性があるかないかだけで判断するため、属性値はどんな内容でも結果は変わりません(3)~(10)。

ただし、HTMLではなくXHTML形式の場合には値を省略した記述はできません。そこだけ気をつけましょう。

  1. … <input type="checkbox" checked>
  2. … <input type="checkbox" checked="checked">
  3. … <input type="checkbox" checked="true">
  4. … <input type="checkbox" checked="false">
  5. … <input type="checkbox" checked="null">
  6. … <input type="checkbox" checked="undefined">
  7. … <input type="checkbox" checked="">
  8. … <input type="checkbox" checked=" ">
  9. … <input type="checkbox" checked=>
  10. … <input type="checkbox" checked="セガール">

checkboxをsetAttributeなどで操作

setAttribute(), getAttribute(), removeAttribute()はその名のとおりAttribute、 つまりHTMLの属性をJavaScriptで操作するメソッドです。

本来JavaScriptでchecked属性の付けはずし操作するときに、正しいのは 「setAttribute("checked", "checked")」と「removeAttribute("checked")」の組み合わせです。 ただし、属性値には何を設定しても無視されるため、 「setAttribute("checked", …)」とすれば、「…」の内容にかかわらずチェックが入ります。

まれに「setAttribute("checked", true)」としているコードを見かけます。 checked属性は一応付きます。しかしおそらくは、プロパティでの操作「checked = true」 と区別が付いていない人の勘違いコードだと思われます。そのような人はチェックをはずしたいと思い 「setAttribute("checked", false)」と書くのだと思いますが、 期待に反してチェックが付いてしまうので混乱してしまうでしょう。

気をつけなければならないのは、ユーザ操作でチェックボックスをクリックしチェックの状態を変えても、 HTMLの属性が変化するわけではないということです。HTMLの属性はあくまでも初期表示の状態のみを規定するものだと考えた方がいいでしょう。

そして、setAttribute, removeAttributeはHTMLの属性をJavaScriptで操作するメソッドです。 あくまでも属性の操作に過ぎず、チェック状態の変更ではないという点に注意が必要です。

また、ユーザ操作でチェックボックスのチェックの状態を変えた場合、 それ以降にsetAttribute, removeAttributeで属性を変更してもチェックの状態は変わりません (主要ブラウザの2014/10/25時点の最新バージョン:Chrome37, IE11, Forefox33)。 ですのでチェックの状態を変更する目的でsetAttribute, removeAttributeを使わないようにするか、 初期表示の操作に限った使用にとどめるべきです。

←操作対象のチェックボックス

チェックがつくグループ

document.getElementById("c1").setAttribute("checked", ★); ※ボタンのラベルは★の内容。どれでもチェックがつく。


チェックがはずれるグループ

document.getElementById("c1").removeAttribute("checked");
※JavaScriptで属性を操作しチェックボックスのチェックをはずすには、属性を削除するしかない。

checked属性値の確認

checkboxをElementオブジェクトのcheckedプロパティで操作

JavaScriptでチェックボックスのチェック状態を変更する場合には、 通常はElementオブジェクトのcheckedプロパティを使用します (少なくとも私は)。 Elementオブジェクトのcheckedプロパティは、HTMLの属性を操作するわけではありません。 そのため、checkedプロパティでチェックの状態を変更してもgetAttribute("checked")の結果は変わりません。

←操作対象のチェックボックス
document.getElementById("c2").checked = ★; ※ボタンのラベルは★の内容。

チェックがつくグループ

※boolean型にパースした時にtrueになる値

チェックがはずれるグループ

※boolean型にパースした時にfalseになる値

checked属性値の確認

参考:JavaScript - disabledへの値の設定の仕方いろいろ - Miuran Business Systems

ここまでのまとめ

ここまで話まとめておきます。

ようやくjQueryのattrとpropの話

ここまで話してようやくjQueryのattrとpropの話に入れます。これまで見てきたように HTMLの属性をJavaScriptで操作することElementオブジェクトのプロパティを操作することは明確に違います。

jQueryの作成者の意図としては、attr()は属性の操作を目的として作成したはずです。 すなわち「setAttribute, getAttribute」と同等の役割にすることを目指して。 ついでに言うとremoveAttrは「removeAttribute」と同等の役割。 そしてpropは、Elementオブジェクトに存在するプロパティを使った操作と同等の役割を期待して作成したはずです。

公式のドキュメント「jQuery API Documentation」 にもそれらしいことが書いてありますし。

.attr()
Get the value of an attribute for the first element in the set of matched elements or set one or more attributes for every matched element.
.prop()
Get the value of a property for the first element in the set of matched elements or set one or more properties for every matched element.

実際おおむねそうなっています。しかし残念なことに部分的に異なっており、 jQueryのバージョンによっても若干動きが異なる部分が発生しています。jQueryのattr()とprop()メソッドを使用した例を jQueryバージョン別に見ていきましょう。

リンクはたくさんありますが、SCRIPTタグのSRCに指定するjQueryのバージョンが異なるだけで内容は同じです。 興味のあるバージョンを1つ2つ見るだけでいいと思います。

バージョンごとの attr() を使って checked を操作するときの動き

バージョンごとの prop() を使って checked を操作するときの動き

attr()はもともと、属性とプロパティの両方を扱おうとしたため仕様に無理がありました。そこで 1.6.0で属性とプロパティの扱いを分離し、属性はattr()で、プロパティはprop()で扱おうとしました。

prop()はプロパティだけを扱うよう新しく設けられたため、はじめからあるべき形の仕様だったのですが、 attr()は過去のバージョンとの互換性を保とうとしたため段階的に仕様変更を行った、 ということなのではないかと思います。特に1.6.0~1.8.3までは移行段階として、 attr()なのにプロパティの操作も行う中途半端な仕様にしていたのだと思います。

そのせいで1.8.3以前、つまり2013年1月以前の古い情報サイトやブログなどでは 「checked, selected, readonly, disabled」の操作なのにattr()を使用するサンプルを提示していたり、 attr()はプロパティの操作も行うことができるかのような説明をするサイトがあるのだと思います。 実際1.8.3まではそれでも正しかったわけですから。

しかし1.9.0以降の新しいバージョンでは仕様が変わっています。新しいバージョンを使用する際には 古いサイトの情報は信用しないようにしましょう。

※こちらのサイト「jQuery1.6のattr()で困ったら、1.6.1にすればいいみたい。 | Ginpen.com」 では、1.6と1.6.1の違い、変更の経緯、どちらのメソッドを使うべきかの一覧の情報があり参考になります。