再掲:javascriptでActiveRecordっぽくハッシュを検索するコードの断片

2011年の投稿ですが個人的によくできたと思ったので再掲します

記事

javascriptrubyと同様にインスタンス*1に対して動的にフィールドを追加できるようだ。javascriptなのでバインドは名前を付けた関数でも可能である。
ということでActiveRecordみたいな手触りのものが作れる。
めっぽう簡単なコードで。
今のところ機能として絞り込み(and検索)にも対応しているが都度実処理してしまっているところを最終段階まで遅延させたいところ。

// コード
var AR = {
    Init : function(hash){
      //関数をバインド
      for(x in this)
         if(typeof this[x] == "function")
            hash[x] = this[x];
      return hash;
    },
    find :function(k) {
        //関数をバインド
        for(x in this)
          if(typeof this[x] == "function")
             this[k][x] = this[x];
        return this[k];
    },
    query : function(m){
        //検索クロージャ
        this.selecta = function(finder,_this,qs){
            var ret = {};
            //検索をしつつ絞り込みのために関数もバインド    
            for(x in _this){
                if(qs == _this[x][finder])
                    ret[x] = _this[x];                
                else if(typeof _this[x] == "function")
                    ret[x] = _this[x];
            }
            return ret;
        };
        this.finder = m;
        return this;
    },
    is :function (qs){ // 検索を実行
       return this.selecta(this.finder,this,qs);
    },
    clean : function(){
       // バインドした関数を取り外す
       for(x in this)
         if(typeof this[x] == "function")
            delete(this[x]);
       return this;
    }
};
//対象データ 
var datasource = {
    tableA : { 
               rowA: { field1 : 1,field2 : 1, field3 : 4 } ,
               rowB: { field1 : 2,field2 : 1, field3 : 5 } ,
               rowC: { field1 : 3,field2 : 2, field3 : 6 } ,
               rowD: { field1 : 4,field2 : 2, field3 : 7 } ,
               rowE: { field1 : 5,field2 : 3, field3 : 8 } ,
               rowF: { field1 : 5,field2 : 3, field3 : 9 } 
            },
    tableB : { 
               rowA: { field1 : 1,field2 : 1, field3 : 4 } ,
               rowB: { field1 : 2,field2 : 1, field3 : 5 } ,
               rowC: { field1 : 3,field2 : 2, field3 : 6 } ,
               rowD: { field1 : 4,field2 : 2, field3 : 7 } ,
               rowE: { field1 : 5,field2 : 3, field3 : 8 } ,
               rowF: { field1 : 5,field2 : 3, field3 : 9 } 
            },
    tableC : { 
               rowA: { field1 : 1,field2 : 1, field3 : 4 } ,
               rowB: { field1 : 2,field2 : 1, field3 : 5 } ,
               rowC: { field1 : 3,field2 : 2, field3 : 6 } ,
               rowD: { field1 : 4,field2 : 2, field3 : 7 } ,
               rowE: { field1 : 5,field2 : 3, field3 : 8 } ,
               rowF: { field1 : 5,field2 : 3, field3 : 9 } 
            }
};
//使い方
var ret = AR.Init(datasource).find("tableB").query("field2").is(2).clean();
for(x in ret)
  console.log(ret[x].field1 + " - " + ret[x].field2 + " - " + ret[x].field3 );
/*
3 - 2 - 6
4 - 2 - 7
*/
//絞り込み
var ret = AR.Init(datasource).find("tableB").query("field2").is(2).query("field1").is(3).clean();
for(x in ret)
  console.log(ret[x].field1 + " - " + ret[x].field2 + " - " + ret[x].field3 );
/*
3 - 2 - 6
*/

都度回すよりも簡単です。ハッシュはjavascriptでも(やはり)速いので配列よりもハッシュがこのましい。
配列を回すと処理時間が不安定なのでsetTimeoutとか使って処理をバックグラウンドで行う場合にはやはりハッシュが好ましいです。

速度

dev状態のmusicdbで使用しているが軽快っぽい
http://lovesaemi.daemon.asia/musicdb_dev/

*1:呼び方知らない