jQuery の data() 等のダッシュ(-)を含むキーの取り扱いの違い
jQuery.data()
やjQuery.fn.data()
を
使うと要素(やオブジェクト)ごとに Key-Value の形でデータを
保存することが出来ます。
また、jQuery.fn.data()
では HTML 属性 data-*
の値を取得することができます。
この属性 data-* まわりの処理のためか、
キーにダッシュ(-
)が含まれている場合、
処理に一貫性が無くなり、1.x 系と 2.x 系で振る舞いが
異なる箇所も出てきます。
そのようなわけで、キーにダッシュが含まれている場合に どのような振る舞いになるのかを調べてみましたが、 キーにダッシュを含めなければいい話なので、 元々キーにダッシュを含めていない人は もうこれ以降読む必要が無いかもしれません。
主に jQuery 2.1.0 と 1.11.0 (あとおざなりに 2.0.3, 1.10.2, 1.9.1) を使って調べたので、他のバージョンでは 当てはまらないことがあるかもしれませんのでご注意下さい。
-
jQuery.fn.data()
での取り扱い -
jQuery.data()
での取り扱い -
jQuery.removeData()
,jQuery.fn.removeData()
での取り扱い - まとめ
- おまけ:データを空にしたときの注意点
jQuery.fn.data()
での扱い
jQuery.fn.data( key, value )
の場合
key に文字列でダッシュ付きキーを、value に値を指定した場合、 基本的にはキーはキャメルケースに変換されて登録されます。 しかし 2.x 系では、 最初(そのキャメル化キーでデータが未登録の場合)は キャメル化キーのみで登録されますが、 2回目(そのキャメル化キーでデータが登録済みの場合)は キャメル化キーだけでなくダッシュ付きキーでも登録されます。
// ※ダッシュ付きをスネークケースと勘違いしていますが無視して下さい
var elem = document.createElement("div");
// fn.data() の場合
// 基本、キーはキャメル化されて登録されるが、、、
// 最初(正確にはそのキーでデータ登録されてない場合)は
// キャメル化キーのみ
$( elem ).data("snake-case", 30);
console.log( $( elem ).data() );
// → Object { snakeCase=30}
// 2回目以降はダッシュ付きキーも共に登録される(2.x系)
$( elem ).data("snake-case", 50);
console.log( $( elem ).data() );
// →Object { snakeCase=50, snake-case=50}
リストに戻る
jQuery.fn.data( obj )
の場合
オブジェクトを指定するとプロパティ名がキーとして、 プロパティの値がそのキーの値として登録されます。 オブジェクトを指定してダッシュ付きキーを指定した場合は、 キャメル化されずにそのままのキーで登録されます。
// ※上の続き
// オブジェクトを指定して登録する場合はキャメル化されない
$( elem ).data({ "snake-case": 75});
console.log( $( elem ).data() );
// →Object { snakeCase=50, snake-case=75}
リストに戻る
jQuery.fn.data( key )
の場合
キーだけを指定するとそのキーの値が読み出されますが、 ダッシュ付きキーだけを指定した場合、まずダッシュ付きキー そのままで値が登録されているか調べ、登録されていなければ 次にキャメル化キーを試し、それも無ければ HTML の data-* 属性を調べます。
// ※上の続きではない
var elem = document.createElement("div");
// fn.data( key ) の読み出しは
// 生キー → キャメル化キー → data-* 属性 の順
$( elem ).attr("data-snake-case", 50);
console.log( $( elem ).data("snake-case") );
// →50
// ※この時点で data には キー"snakeCase"・値50 のデータが入る
$( elem ).data("snakeCase", 100);
console.log( $( elem ).data("snake-case") );
// →100
$( elem ).data({ "snake-case": 150 });
console.log( $( elem ).data("snake-case") );
// →150
リストに戻る
jQuery.data()
での取り扱い
jQuery.data( elem, key, value )
の場合
key に文字列でダッシュ付きキーを、value で値を指定した場合、 2.x 系ではダッシュ付きキーそのままで登録されますが、 1.x 系ではキャメル化キーで登録されます。
// ※elem は DOM 要素
// jQuery.data( elem, key, value ) は
// 2.x 系では生キー、1.x 系ではキャメル化キーで登録
jQuery.data( elem, "snake-case1", 50);
jQuery.data( elem, "snake-case2", 100);
console.log( jQuery.data( elem ) );
// 1.x 系
// →Object { snakeCase1=50, snakeCase2=100}
// 2.x 系
// →Object { snake-case1=50, snake-case2=100}
リストに戻る
jQuery.data( elem, obj )
の場合
ダッシュ付きキーをオブジェクトで指定した場合は
jQuery.fn.data()
と同じく
キャメル化されずにそのままのキーで登録されます。
// ※elem は DOM 要素
// jQuery.data( elem, obj ) は
// そのままのキーで登録
jQuery.data( elem, { "snake-case1": 30,
"snake-case2": 60 });
console.log( jQuery.data( elem ) );
// →Object { snake-case1=30, snake-case2=60}
リストに戻る
jQuery.data( elem, key )
の場合
ダッシュ付きキーだけを指定した場合、まずダッシュ付きキー
そのままで値が登録されているか調べ、登録されていなければ
次にキャメル化キーを試します。
jQuery.fn.data()
と違って
HTML の data-* 属性は調べません。
// ※上の続きではない
var elem = document.createElement("div");
// jQuery.data( elem, key ) の読み出しは
// 生キー → キャメル化キー の順
$( elem ).attr("data-snake-case", 50);
console.log( jQuery.data( elem, "snake-case") );
// →undefined
jQuery.data( elem, { "snakeCase": 100 });
console.log( jQuery.data( elem, "snake-case") );
// →100
jQuery.data( elem, { "snake-case": 150 });
console.log( jQuery.data( elem, "snake-case") );
// →150
リストに戻る
jQuery.fn.removeData()
,
jQuery.removeData()
での取り扱い
jQuery.fn.removeData()
,
jQuery.removeData()
は指定したキーを削除します。
キーの指定方法には単数指定(文字列)と
複数指定(配列、空白で区切った文字列)があります。
キーを指定しないと全削除になります。
一つのキーを削除する場合(.removeData(key)
)
キーを文字列値で指定するとそのキーが削除されます。 2.x 系ではそのままのキーとキャメル化キーの両方が 削除されますので、ダッシュ付きキーを指定した場合は ダッシュ付きキーとキャメル化キーの両方が削除されます。 1.x 系ではそのままのキーが存在したらそのキーを削除して その時点で終了し、無ければキャメル化キーの存在を調べて 削除します。 つまり 1.x 系ではダッシュ付きキーとキャメル化キーの両方が 存在した場合、ダッシュ付きキーを指定しても キャメル化キーが削除されません。
// ※jQuery.fn.removeData と jQuery.removeData は
// ダッシュ付きキーの処理に関しては同じ
var elem = document.createElement("div");
// キー一つを指定した場合、
// 1.x 系では キーそのまま→キャメル化されたキー の順に
// 調べて見つかった時点でそのキーを削除して終了する
// 2.x 系では キーそのまま と キャメル化されたキーを
// 両方削除する
$( elem ).data({ "snake-case1": 25,
"snake-case2": 50,
"snakeCase1": 75,
"snakeCase2": 100 });
console.log( $( elem ).data() );
// →Object { snake-case1=25, snake-case2=50,
// snakeCase1=75, snakeCase2=100 }
$( elem ).removeData("snake-case1");
console.log( $( elem ).data() );
// 2.x 系
// →Object { snake-case2=50, snakeCase2=100}
// 1.x 系
// →Object { snake-case2=50, snakeCase1=75, snakeCase2=100}
$( elem ).removeData("snakeCase2");
console.log( $( elem ).data() );
// 2.x 系
// →Object { snake-case2=50}
// 1.x 系
// →Object { snake-case2=50, snakeCase1=75}
リストに戻る
複数のキーを削除する場合
(.removeData([key1, key2, ...])
,
.removeData("key1 key2 ...")
)
複数キーの指定方法は2種類あります。 一つはキー(文字列)の配列を指定する方法で、 この指定方法ではそのままのキーとキャメル化キーの両方が 削除されます。 もう一つは空白で区切った文字列で指定する方法で、 この指定方法ではキャメル化キーのみが削除されます。 つまり文字列指定では、 ダッシュ付きキーとキャメル化キーの両方が存在した場合に ダッシュ付きキーを指定してもキャメル化キーしか削除されません。
// ※elem は DOM 要素
// 配列指定の場合はキャメル化されたキーも削除される
$( elem ).data({ "snake-case1": 25,
"snake-case2": 50,
"snakeCase1": 75,
"snakeCase2": 100 });
console.log( $( elem ).data() );
// →Object { snake-case1=25, snake-case2=50,
// snakeCase1=75, snakeCase2=100 }
$( elem ).removeData(["snake-case1", "snake-case2"]);
console.log( $( elem ).data() );
// →Object {}
// 空白で区切った文字列での指定の場合はキャメル化された
// キー「のみ」削除される
$( elem ).data({ "snake-case1": 25,
"snake-case2": 50,
"snakeCase1": 75,
"snakeCase2": 100 });
console.log( $( elem ).data() );
// →Object { snake-case1=25, snake-case2=50,
// snakeCase1=75, snakeCase2=100 }
$( elem ).removeData("snake-case1 snake-case2");
console.log( $( elem ).data() );
// →Object { snake-case1=25, snake-case2=50}
リストに戻る
まとめ
ダッシュ付きのキーを使わないようにしましょう。
使う場合でも、
jQuery.fn.data()
とjQuery.data()
を
混ぜこぜで使ったり、
複数のキーを操作する便利な用法を使ったりしなければ
大丈夫だと思います。
-
jQuery.fn.data()
-
キー登録(
data(key, value)
)- 2.x 系
最初(キャメル化キーに未登録)はキャメル化キーのみ
2回目(キャメル化キーに登録済)は生キーも共に
- 1.x 系
キャメル化キーのみ
- 2.x 系
-
キー登録(
data(object)
)生キー
-
キー読み出し(
data(key)
)生キー → キャメル化キー → data- 属性 の順
-
キー登録(
-
jQuery.data()
-
キー登録(
data(key, value)
)- 2.x 系
生キー
- 1.x 系
キャメル化キー
- 2.x 系
-
キー登録(
data(object)
)生キー
-
キー読み出し(
data(key)
)生キー → キャメル化キー の順
-
キー登録(
-
jQuery.fn.removeData()
,jQuery.removeData()
- 単数キー(
.removeData(key)
)- 2.x 系
生キー・キャメル化キー 両方
- 1.x 系
生キー → キャメル化キー の順に調べ 初見のキーを削除した時点で終了する
- 2.x 系
- 複数キー
- 配列指定(
.removeData([key1,key2, ...])
)生キー・キャメル化キー 両方
- 文字列指定(
.removeData("key1 key2 ...")
)キャメル化キーのみ
- 配列指定(
- 単数キー(
おまけ:データを空にしたときの注意点
1.x 系では
jQuery.fn.removeData()
や
jQuery.removeData()
を使ってデータを空にした時、
データオブジェクトが変更されます。
2.x 系でも上の2つのメソッドを引数無しで実行してデータを
空にした時はデータオブジェクトが交換されます。
// ※elem は DOM 要素
// 全削除で空にした場合
$( elem ).data({ "snake-case1": 25,
"snake-case2": 50 });
var data1 = $( elem ).data();
console.log( data1 );
// →Object { snake-case1=25, snake-case2=50}
$( elem ).removeData(); // 全削除で空にする
var data2 = $( elem ).data();
console.log( data1 );
// →Object { snake-case1=25, snake-case2=50}
// ※全削除だとデータオブジェクトが交換される
console.log( data2 );
// →Object { }
// キー指定で空にした場合
$( elem ).data({ "snake-case1": 30 });
var data3 = $( elem ).data();
console.log( data3 );
// →Object { snake-case1=30}
$( elem ).removeData(["snake-case1"]); // キー指定で空にする
var data4 = $( elem ).data();
console.log( data3 );
// →Object { }
console.log( data4 )
// →Object { }
console.log( data3 === data4 );
// 2.x 系
// →true
// 1.x 系
// →false
// ※1.x 系だと削除後、データオブジェクトが空の場合
// キャッシュからデータオブジェクトも削除されるため、
// その後の操作で再生成されるデータオブジェクトは
// 以前のデータオブジェクトと異なる
リストに戻る