jQueryの$elm.data()で取得できる値は暗黙でstringから型変換される
Posted: Updated:
知らなくてコケた
通常,element.datasetから得られるカスタムデータ属性の値はstringですが,jQueryのdataメソッドはこれらを暗黙的に型変換します.
以下コード踏まえたサンプル.
<!-- 長いので改行いれてます --> <div id="test" data-str="hogefuga" data-num="01234" data-bool="true" data-ary="[1,2,3]" data-obj='{"foo":"bar"}'> <p>ほげほげほげ</p> </div>
たとえば,このようなdata-*がコッテリ付いた要素があったとして,その要素から$elm.data()で値を取得すると・・・
var $elm = $('#test'); // string $elm.data('str'); // 'hogefuga' // number $elm.data('num'); // 1234 // boolean $elm.data('bool'); // true // array $elm.data('ary'); // [1,2,3] // object $elm.data('obj'); // {foo:'bar'}
なんと型変換されます.オブジェクトっぽい文字列はobjectに変換されますし,その他それっぽい文字列はそれっぽい型に変換されて渡されます.
自分がコケたのは,例にも挙げたようなnumericだけど先頭が0のstringを,numberに変換されて1234なってしまっていたパターン.仕様を把握してませんでした.lol
確実にstringのまま取得したいならattrを使う
Every attempt is made to convert the string to a JavaScript value (this includes booleans, numbers, objects, arrays, and null) otherwise it is left as a string. To retrieve the value's attribute as a string without any attempt to convert it, use the attr() method..data() – jQuery API
dataメソッドはstringから色々型変換しちゃうから,ピュアなstringで取得したいならattr使うといいよ,という話でした.
ドキュメント読んでなかった自分が悪いのは棚に上げつつ,キモいすごく親切ですね.
追記おまけ
jQuery source viewerから変換部分の実装拾ってきた.うーん...直球(;´Д`)
// `dataAttr` from 1.7pre Live From Git (3ad0ba62f03ff3d7aec7d3dfb25492cdf33350a7) function dataAttr(elem, key, data) { // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute if (data === undefined && elem.nodeType === 1) { var name = "data-" + key.replace(rmultiDash, "-$1").toLowerCase(); data = elem.getAttribute(name); if (typeof data === "string") { try { data = data === "true" ? true : data === "false" ? false : data === "null" ? null : jQuery.isNumeric(data) ? parseFloat(data) : rbrace.test(data) ? jQuery.parseJSON(data) : data; } catch(e) {} // Make sure we set the data so it isn't changed later jQuery.data(elem, key, data); } else { data = undefined; } } return data; }
個人的には,$elm.data(key[, type])ぐらいにして,typeの明示があったときだけ変換してくれればいいと思う.実際はsetとgetのインターフェース混ざってるからできなさそうだけど.