« ECS 3.0サービス終了に伴う『蔵書リンクMAKER』の改修 | トップページ | 【JavaScript】ベンチをとってみる<オブジェクトをキーに出来るハッシュのようなもの »

2008/02/13

【JavaScript】オブジェクトをキーに出来るハッシュのようなもの……って、これじゃだめ?

すべてのオブジェクトをキーにできるハッシュの様なもの - IT戦記を見て。
どうやったら効率的なものを書けるだろうか
単純に、こんなのじゃだめでしょうか?
キーになるオブジェクトを汚しているけど(w

■[2008/02/14]
for (name in key)とすると、想定外の余計なものまでとれてしまうのはやはりちとまずいように思えたので、keyの直下ではなく、key.toString下にvalueを生やす方向で修正。
もちろん、for (name in key.toString)ってやったり、key.toStringを途中で置換したりとかするとまずいわけですが(keyオブジェクトの生成直後に置換するぶんには問題無し)、まぁ、あんましやらないかと(^^;)。

ん~、toString()を置き換えると、DontEnum属性が外れて、for (name in key)でひっかかるようになっちゃうのか(IEを除く)……まぁ、仕方ないよね(ヲ。

■[2008/02/17]
上書き登録したときに、getKeys()の戻り値がおかしかったので修正。
#ついでに、getKeys()で戻すのはその時点のSnapshotにした。
■ソース(ライブラリファイル化したものはこちら)
Object.associativeArray=(function(){
    var count=0;
    return function(){
        var assocaObj=this;
        var keys=[];
        
        var assoca=[],assocastr='__associativeArray'+(count++)+'__';
        assoca.number=[]; assoca.string=[]; assoca.boolean=[];
        
        assocaObj.set=function(key,value){
            if (assoca[typeof key]) {
                if (assoca[typeof key][key]===undefined) keys[keys.length]=key;
                assoca[typeof key][key]=value;
            }
            else {
                if (!key.toString.__associativeFlag__) {
                    var orgToString=key.toString;
                    key.toString=function(){return orgToString.apply(key,arguments)};
                    key.toString.__associativeFlag__=true;
                }
                if (key.toString[assocastr]===undefined) keys[keys.length]=key;
                key.toString[assocastr]=value;
            }
            return value;
        };
        assocaObj.get=function(key){
            if (assoca[typeof key]) {
                return assoca[typeof key][key];
            }
            else {
                return key.toString[assocastr];
            }
        };
        assocaObj.remove=function(key){
            var value=assocaObj.get(key);
            var tmpKeys=[];
            for (var ci=0,len=keys.length; ci<len; ci++) {
                if (keys[ci]!==key) tmpKeys[tmpKeys.length]=keys[ci];
            }
            keys=tmpKeys;
            if (assoca[typeof key]) {
                assoca[typeof key][key]=undefined;
            }
            else {
                key.toString[assocastr]=undefined;
            }
            return value;
        };
        assocaObj.getKeys=function(){
            return keys.concat([]);
        };
        assocaObj.collect=function(keyList){
            var collection=[];
            if (!keyList) keyList=keys;
            for (var ci=0,len=keyList.length; ci<len; ci++) {
                collection[collection.length]=assocaObj.get(keyList[ci]);
            }
            return collection;
        };
    };
})();
実行例
// === ハッシュ用オブジェクト作成
var assoca1 = new Object.associativeArray();

// キーが数値の1
assoca1.set(1, 2);
// キーが文字の'1'
assoca1.set('1', 3);
// キーが関数
var f=function(){print('hoge')};
var g=function(){print('fuga')};
assoca1.set(f, 4);
assoca1.set(g, 5);
// キーが真偽値
assoca1.set(true,6);
assoca1.set(false,7);
// キーがDOMオブジェクト
var DOM=document.body.lastChild;
assoca1.set(DOM,8);

// それぞれ設定通りの値が得られる
print(" 1   → "+assoca1.get(1));     // → 2
print("'1'  → "+assoca1.get('1'));   // → 3
print(" f   → "+assoca1.get(f));     // → 4
print(" g   → "+assoca1.get(g));     // → 5
print("true → "+assoca1.get(true));  // → 6
print("false→ "+assoca1.get(false)); // → 7
print("DOM  → "+assoca1.get(DOM));   // → 8

// キーリスト取得
print("keys   → "+assoca1.getKeys().join(', ')); // → 1, 1, function(){print('hoge')}, function(){print('fuga')}, true, false, [object]

// 値リスト取得
print("values → "+assoca1.collect().join(', ')); // → 2, 3, 4, 5, 6, 7, 8

// キー削除
print("remove f → "+assoca1.remove(f)); // → 4

// 新たに正規表現オブジェクトをキーに
var r=/test/gi;
assoca1.set(r,9);
print(" r   → "+assoca1.get(r));     // → 9

// キーリスト取得
print("keys   → "+assoca1.getKeys().join(', ')); // → 1, 1, function(){print('fuga')}, true, false, [object], /test/ig
print("values → "+assoca1.collect().join(', ')); // → 2, 3, 5, 6, 7, 8, 9

// === 新規にハッシュ用オブジェクト作成
var assoca2 = new Object.associativeArray();

// キーが配列
var array=[1,2,3];
assoca2.set(array,'ARRAY');
print("assoca2.get(array)   → "+assoca2.get(array));   // → ARRAY
print("assoca2.get([1,2,3]) → "+assoca2.get([1,2,3])); // → undefined

// 先のハッシュ用オブジェクトに用いたキーを使用
assoca2.set(g,'TEST');
print("assoca1.get(g) → "+assoca1.get(g));  // → 5
print("assoca2.get(g) → "+assoca2.get(g));  // → TEST

« ECS 3.0サービス終了に伴う『蔵書リンクMAKER』の改修 | トップページ | 【JavaScript】ベンチをとってみる<オブジェクトをキーに出来るハッシュのようなもの »

パソコン・インターネット」カテゴリの記事

おもいつき」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

« ECS 3.0サービス終了に伴う『蔵書リンクMAKER』の改修 | トップページ | 【JavaScript】ベンチをとってみる<オブジェクトをキーに出来るハッシュのようなもの »

戻るリンク追加

カレンダー

2019年9月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          

ココログカレンダーPlus

検索


    • Web全体 サイト内
    • 蔵書のISBNを入力して下さい
    • はじめる前
      初級者向け
      上級者向け
      ブログ紹介
      結果を表示

最近のトラックバック

コメントリストツリー化

無料ブログはココログ