【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にした。
↓
■[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 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
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】ベンチをとってみる<オブジェクトをキーに出来るハッシュのようなもの »
「パソコン・インターネット」カテゴリの記事
- Twitter 原寸びゅー:PC版ブラウザ用・Twitterの画像閲覧と保存がはかどる拡張機能の紹介(2016.02.12)
- スマートフォンをPC上の音楽を再生するためのリモコンとして使いたい(2016.01.10)
- BIGLOBE光ネクスト(大阪)の通信速度問題 - プロバイダ選びは難しい……(2015.08.13)
- BOOK☆WALKER さんに関して最近経験した不安と不満(2015.08.10)
- 『#鳥獣戯画制作キット』が楽しい(2015.07.01)
「おもいつき」カテゴリの記事
- ココログをTwitterカードに対応させてみる(2016.11.23)
- 神使の兎 ~宇治神社にて~(2016.07.10)
- Twitter 原寸びゅー:PC版ブラウザ用・Twitterの画像閲覧と保存がはかどる拡張機能の紹介(2016.02.12)
- スマートフォンをPC上の音楽を再生するためのリモコンとして使いたい(2016.01.10)
- 【覚書】風柳亭(ココログプロ)をレスポンシブWebデザイン化(Bootstrap3使用)(2015.10.09)
« ECS 3.0サービス終了に伴う『蔵書リンクMAKER』の改修 | トップページ | 【JavaScript】ベンチをとってみる<オブジェクトをキーに出来るハッシュのようなもの »
コメント