かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

jQuery $.data()と.data()、データの保存と取得で気をつけること。

jQueryのパフォーマンスを下げるアンチパターンに関する超意訳 - Qiita こちらの記事に

data()
// 普通の書き方
$(elem).data(key, value);

// 10倍速い!
$.data(elem, key, value);

とあったので、$.data(elem, key, value);を使おうとして少し気になる挙動になったのでメモです。 確認環境のjQueryのバージョンは1.10.2です。($.fn.jqueryjQueryのバージョンが確認できます。)

リファレンスのメモ

.data()

.data() | jQuery API Documentation
.data() | jQuery 1.9 日本語リファレンス | js STUDIO

  • データを格納する
    .data(key, value)
    引数説明
    key要素に紐付けるデータのキーとなる文字列を指定します。
    value格納するデータを指定します。 このデータは配列、オブジェクトを含むいくつかのjavaScriptの型の値を指定することが可能です。
  • データを取得する
    .data(value)
    引数説明
    key要素に紐付いているキーを指定して、データを取得します。

$('body').data('foo', 52); // データ( 52 )を格納
$('body').data('foo'); // データ( 52 )を取得

$.data()

jQuery.data() | jQuery API Documentation
$.data() | jQuery 1.9 日本語リファレンス | js STUDIO

  • 要素に対してデータを格納する
    $.data( element, key, value )
    引数説明
    elementデータを紐付ける要素を指定します。
    key要素に紐付けるデータのキーとなる文字列を指定します。
    value格納するデータを指定します。 このデータは配列、オブジェクトを含むいくつかのjavaScriptの型の値を指定することが可能です。
  • 要素から指定したキーで格納されているデータを取得する
    $.data( element, key )
    引数説明
    element取得したいデータを格納している要素を指定します。
    key要素に紐付いているキーを指定して、データを取得します。

$.data(document.body, 'foo', 52); // データ( 52 )を格納
$.data( document.body, 'foo' ) // データ( 52 )を取得

 


 
#ship というエレメントにdataを使って値を保存して付けてみたいと思います。

$.data('#ship', 'Destroyer', '響');
// Uncaught TypeError: Cannot read property 'data' of undefined

エラーになってしまいました。
$.data( element, key, value )なので、'#ship'という文字列ではエラーになって当然ですね。

一旦jQueryオブジェクト化してみます。

var $ship = $('#ship');
// jQueryオブジェクトのままデータを保存
$.data($ship, 'Destroyer', '響');
// $ship[0] でDOM要素にしてデータを保存
$.data($ship[0], 'HeavyCruiser', 'Prinz Eugen');

どちらでも問題なく$.data()を使って値が保存できたようです。
しかし!!!
この値を取得したい時にどう保存したかによって取得のされ方が異なっていました!

1. jQueryオブジェクトのままデータを保存した場合

var $ship = $('#ship');
$.data($ship, 'Destroyer', '響');

// 値を取得する
$.data($ship, 'Destroyer');     // "響"
$.data($ship[0], 'Destroyer');  // undefined
$ship.data('Destroyer');        // undefined
$('#ship').data('Destroyer');   // undefined

$.data(jQueryオブジェクト, key)以外ではデータを取得することができませんでした

 

2. [0], get(0)でDOM要素にしてデータを保存

var $ship = $('#ship');
$.data($ship[0], 'HeavyCruiser', 'Prinz Eugen');

// 値を取得する
$.data($ship, 'HeavyCruiser');     // undefined
$.data($ship[0], 'HeavyCruiser');  // "Prinz Eugen"
$ship.data('HeavyCruiser');        // "Prinz Eugen"
$('#ship').data('HeavyCruiser');   // "Prinz Eugen"

今度は逆に$.data(jQueryオブジェクト, key)とするとデータが取得できません
こちらのパターンではよく使う.data()でもデータを取得することができます

 

3. それぞれのデータの保存方法で同じキーを使ってしまった場合

なんとなく$.data($ship, key, value)$.data($ship[0], key, value)で同じキーでも別に保存できてしまいそうな気がします。

var $ship = $('#ship');
$.data($ship, 'Destroyer', '響');
$.data($ship[0], 'Destroyer', '吹雪');

// 値を取得する
$.data($ship, 'Destroyer');     // "響"
$.data($ship[0], 'Destroyer');  // "吹雪"
$ship.data('Destroyer');        // "吹雪"
$('#ship').data('Destroyer');   // "吹雪"

予測通りでした。

  • $.data($ship, key, value)で付けた値は
    $.data($ship, key)
    でのみ取得できる
  • $.data($ship[0], key, value)で付けた値は
    $.data($ship[0], key)
    $ship.data(key)
    $('#ship').data(key)
    で取得できる

 

4. $.data()でデータを上書きしてしまった場合

var $ship = $('#ship');
// データを保存
$.data($ship, 'Destroyer', '響');
$.data($ship[0], 'Destroyer', '吹雪');

// データを上書き
$ship.data('Destroyer', '雪風');

// 値を取得する
$.data($ship, 'Destroyer');     // "響"
$.data($ship[0], 'Destroyer');  // "雪風"
$ship.data('Destroyer');        // "雪風"
$('#ship').data('Destroyer');   // "雪風"

// データを保存
$.data($ship, 'HeavyCruiser', 'Blücher');
$.data($ship[0], 'HeavyCruiser', 'Prinz Eugen');

// 新しくjQueryオブジェクト化してデータを上書きする
$('#ship').data('HeavyCruiser', '妙高!');

// // 値を取得する
$.data($ship, 'HeavyCruiser');     // "Blücher"
$.data($ship[0], 'HeavyCruiser');  // "妙高!"
$ship.data('HeavyCruiser');        // "妙高!"
$('#ship').data('HeavyCruiser');   // "妙高!"

ちくしょう!プリンツ・オイゲンちゃんが妙高ねぇさんに置き換えられちまった!!
はい。 こちらも大方予想された通り、$.data($ship[0], key, value)で付けた値は$ship.data(key, value)で更新する事ができるようです。  
 


 
$.data(elemet, key, value)でデータを保存させる時elementをDOM要素にする時は、
$(element).data()key及びvalueが共用される事を意識しておいたほうが良さそうです!値が取得しやすい分、意図せず上書きしてしまうかもしれないので。

逆にelementをjQueryオブジェクト( $(element) )にした時は、
$.data($(element), key)でしか値を取得できない事を覚えておかないと意図せずundefinedしか取得できないでバグが発生するとかありそうです。

ちなみに僕はベルヌイちゃんより響ちゃんが好きです!
よろしくお願いします。