読者です 読者をやめる 読者になる 読者になる

素人がプログラミングを勉強していたブログ

プログラミング、セキュリティ、英語、Webなどのブログ since 2008

連絡先: すかいぷ:javascripter_  か javascripter あっと tsukkun.net skypeのほうがいいです

Node#setUserData、Node#getUserDataの使い方(jQuery.dataみたいなもの)

javascript

setUserDataとgetUserDataが便利。

var o = {};
o[document.body] = 12345;

みたいなことができなくて困ってたのだけど、こういう場合はsetUserDataとgetUserDataが使える。
基本的な使い方は、

document.body.setUserData("key", {value: 123}, null);

document.body.getUserData("key");
// Object value=123

のような感じ。setUserDataの第一引数に、ネームスペース用のユニークなキー文字列を入れ、第二引数にオブジェクト(nullを入れると、セットされるのではなく削除される)を入れる。

第三引数には、関数もしくはnullを入れる。関数を入れると、cloneNodeなどのタイミングをトリガーに関数を呼ぶことができる。

例えば、要素を基準としてキャッシュを作りたい場合、このメソッドを使うと要素のプロパティを汚さずに済む。
例:querySelectorAllとgetElementsByClassName、速度比較 - 素人がプログラミングを勉強するブログ


setUserDataが削除も兼ねるっていうのが気に食わない場合、下みたいなラッパーを作るといいと思う。

function elemData() {
  this.all = [];
  this.key = "elementData" + Date.now();
}
elemData.prototype.add = function(elem, data) {
  if (this.get(elem) === null)
    this.all.push(elem);
  elem.setUserData(this.key, [this.all.length, data], null);
  return data;
};
elemData.prototype.get = function(elem) {
  var data = elem.getUserData(this.key);
  return data ? data[1] : data;
};
elemData.prototype.remove = function(elem) {
  var data;
  if (data = this.get(elem))
    this.all.splice(data[0] - 1, 1);
  elem.setUserData(this.key, null, null);
};
elemData.prototype.clear = function() {
  this.all.forEach(this.remove, this);
};
var d = new elemData();
d.add(document.body, 42);
console.log(d.get(document.body)); // 42
d.remove(document.body);
console.log(d.get(document.body)); // null
d.add(document.links[0], "foo");
d.add(document.links[1], "bar");
d.clear();
console.log(d.get(document.links[0])); // null