スマートじゃない DOM 拡張

この数ヶ月、理解しがたい JavaScript の不思議の一つ。json.jsobject.toJSONString() ような感覚で、以下のような感じで DOM にメソッドを追加してみると、

HTMLElement.prototype.hogeHogeHoge = function() {
//  something procedure releted to HTMLElement
};

Firefox などでは問題ないが、IE だとうまくいかない( IE では HTMLElement という考え方がないため)。

prototype.js の場合、 この状況を次のように処理して問題解決している、ように見える。(まるごと JavaScript & AJAX より引用)

// Extending DOM object
var element = Element.extend(document.createElement('div'));

// observe() is extended function
element.observe('click', eventHandler);

// If the element isn't extended, it's able to use observe() by this code.
Element.observe(element, 'click', eventHandler);

Firefox、Safari、IE など主要ブラウザでこのコードで必要な処理ができてはいるが、毎回 Element.extend() するのが冗長な気がする。

それくらいなら document.createElement() で返す DOM そのものを拡張したものに、と思うのだけど、IE では document.createElement() のオーバーライドはできるものの、関連する document.getElementById() などがオーバーライドできないという問題があり(例外になる)、あまりスマートではない。

HTMLElement のラッパーオブジェクトをつくり、そこにメソッドを追加という方法もあるが、それはプロトタイプベースオブジェクト指向言語には冗長なつくりだし、ここはやはり既存オブジェクトの拡張で進めたい、ところではあるが、なかなかうまくいかない。

たとえば Ruby on Rails では、付属の ActiveSupport ライブラリで自動的に数字の型が拡張され、

puts 3.days.ago

みたいな書き方ができる(Integer=>Time の変換)。もちろん 3 は普通の Integer としても扱える。とても自然でスマートで、プログラミング言語とは思えないくらいの直感さがあるように思う。

これ厳密には IE の実装の問題なのだけど、こういった問題がなくならない限り、JavaScript の不可思議さはなくならない気がする。

Leave a Reply