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

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

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

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

オブジェクトをキーにできるハッシュ(object_id)

ただし、Object.prototypeを汚染してしまう。
次の JavaScript の仕様はこうなる! ECMAScript 3.0 から 3.1 への変更点まとめ - IT戦記を見た感じ、ECMAScript3.1だとenumerableをfalseにできるのでObject.prototypeを汚染してもfor(bar in foo)で列挙されなくなるらしい。はやく使いたい。

(function() {
  var uid = 0;
  Object.prototype.__defineGetter__("object_id", function() {
    var n = uid++;
    this.__defineGetter__("object_id", function() n);
    return n;
  });
})();

function Hash() {}
Hash.prototype.add = function(key, value) this[key.object_id] = value;
Hash.prototype.get = function(key) this[key.object_id];
Hash.prototype.remove = function(key) delete this[key.object_id];
Hash.prototype.in =function(key) key.object_id in this;

function uniqElem(elems) {
  var h = new Hash();
  return Array.filter(elems,
    function(i) h.in(i) ? false: h.add(i, true));
}
uniqElem(Array.slice(document.links).concat(Array.slice(document.querySelectorAll("[href]"))));

あと、上の実装だと

var b = false;
b.object_id == b.object_id; // false

になってしまう。関数のthisは必ずオブジェクトになるので、プリミティブ値に対してobject_idが呼ばれたのかどうかを判定できない。
だから、どうしようもないと思う。