Objectオブジェクトのイテレーター

概要: Objectオブジェクトのイテレーターを実装する。


Javascriptにはハッシュが無い。とはいってもObjectオブジェクトをハッシュのように使えるんだけど、 Object.prototypeを拡張すると空のObjectまで汚染されるし、 Object.prototypeにObjectのイテレーターを追加すると、 オブジェクトのキーにイテレーター名が使えなくなってしまう。 (Object.prototype.forEachが実装されていたとすると、object **_forEach*_**が定義されているObjectでは動かなくなる)

じゃあどうしたらいいんだろう、と思っていたんだけど、イテレータとObjectを分離してやればいいんじゃないか、 と言うのを今日ふと思いついた。

実際の実装はこんな感じ。

Object.Iterator = function ( target ) {
if ( typeof(target) != 'object' )
throw new TyprError('Arguments is not object.');
var self = this;
self.target = function () {
return target;
}
}
Object.Iterator.prototype = {
'filter'    : function ( callback, thisObject ) {
if ( typeof(callback) != 'function' )
throw new TypeError('callback is not function');
var obj     = this.target(),
result  = {};
for ( var key in obj ) {
if ( obj.hasOwnProperty(key) ) {
if ( callback.call(thisObject, key, obj key , obj)  ) {
result key  = obj key ;
}
}
}
return result;
},
'each'      : function ( callback, thisObject ) {
if ( typeof(callback) != 'function' )
throw new TypeError('callback is not function');
var obj = this.target();
for ( var key in obj ) {
if ( obj.hasOwnProperty(key) ) {
callback.call(thisObject, key, obj key , obj);
}
}
},
'map'       : function ( callback, thisObject ) {
if ( typeof(callback) != 'function' )
throw new TypeError('callback is not function');
var obj     = this.target(),
result  = {};
for ( var key in obj ) {
if ( obj.hasOwnProperty(key) ) {
result key  = callback.call(thisObject, key, obj key , obj);
}
}
return result;
},
'every'     : function ( callback, thisObject ) {
if ( typeof(callback) != 'function' )
throw new TypeError('callback is not function');
var obj = this.target();
for ( var key in obj ) {
if ( obj.hasOwnProperty(key) && ! callback.call( thisObject, key, obj key , obj ) ) {
return false;
}
}
return true;
},
'some'      : function ( callback, thisObject ) {
if ( typeof(callback) != 'function' )
throw new TypeError('callback is not function');
var obj = this.target();
for ( var key in obj ) {
if ( obj.hasOwnProperty(key) && callback.call( thisObject, key, obj key , obj ) ) {
return true;
}
}
return false;
},
'keys'      : function () {
var obj     = this.target(),
results = [];
for ( var key in obj ) {
if ( obj.hasOwnProperty(key) )
results results.length  = key;
}
return results;
},
'values'    : function () {
var obj     = this.target(),
results = [];
for ( var key in obj ) {
if ( obj.hasOwnProperty(key) )
results results.length  = obj key ;
}
return results;
}
};

で、こうやって使う。

var hash = { 'aaa': 'AAA', 'bbb': 'BBB', 'ccc': 'CCC' };
var iterator = new Object.Iterator( hash );
iterator.keys() //   'aaa', 'bbb', 'ccc'  

こうすれば、Objectオブジェクトを本当のハッシュのように使えると思う。 オブジェクトとイテレーター分離するっていうのはArrayオブジェクトでもできそう。

ちなみに上記コード、一部しかテストしてないため、ちゃんと動くかどうか不明。 そこをさぼってどうするのとか思うわけだけど、実装サンプルなのでそのあたり手抜き。

とりあえずアイディアだけまとめてみた。何につかえるんだろ。

#FIXME

nyarla が大体

Scrapbox でコメントや意見を書く