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のインターフェース混ざってるからできなさそうだけど.