動機
以下のように分岐処理を記載するため、列挙型的データ構造(MY_ENUM
の中身)を考案しました。
const MY_ENUM = {/* ? */};
// ...
const e = MY_ENUM.key0;
// ...
if (e.key0) {
// ...このブロックにはいる...
} else if (e.key1 || e.key2) {
// ...
} else if (e.key3) {
// ...
} else {
// ...
}
この例の場合、列挙型的データ構造は最低限、以下でないといけません。
const MY_ENUM = {
'key0':{'key0':true,},
'key1':{'key1':true,},
'key2':{'key2':true,},
'key3':{'key3':true,},
// ...
};
本案で解決される課題
本案は、以下のようなプログラムから移行するために考案しました。
switch句
分岐が英単語(case
、default
やbreak
)で表されるため見ずらい、break
漏れによる意図しない落下(fall-through)、分岐で字句スコープが作成されない問題、などがあり、好ましく思わない意見があります。
const key = 'key0';
// ...
switch (key) {
case 'key0':
// ...このブロックにはいる...
break;
case 'key1':
case 'key2':
// ...
break;
case 'key3':
// ...
break;
default:
// ...
}
文字列型を使用して判定
key===
冗長記載による可読性の低下が気になります。
const key = 'key0';
// ...
if (key==='key0') {
// ...このブロックにはいる...
} else if (key==='key1' || key==='key2') {
// ...
} else if (key==='key3') {
// ...
} else {
// ...
}
ユニークな値を持つ連想配列(固定化したオブジェクト)
key===MY_ENUM.
冗長記載による可読性の低下が気になります。
const MY_ENUM = Object.freeze({
'key0':0,
'key1':1,
'key2':2,
'key3':3,
// ...
});
// ...
const key = MY_ENUM.key0;
// ...
if (key===MY_ENUM.key0) {
// ...このブロックにはいる...
} else if (key===MY_ENUM.key1 || key===MY_ENUM.key2) {
// ...
} else if (key===MY_ENUM.key3) {
// ...
} else {
// ...
}
連想配列の値に関数を定義
ケースによると考えます。
const MY_ENUM = {
'key0':()=>{/*...このブロックにはいる...*/},
'key1':()=>{/*...*/},
'key3':()=>{/*...*/},
// ...
'defaultKey':()=>{/*...*/},
};
MY_ENUM['key2'] = MY_ENUM['key1'];
Object.freeze(MY_ENUM);
// ...
const key = 'key0';
// ...
(MY_ENUM[key] ?? MY_ENUM['defaultKey'])();
付加情報
最低限の列挙型的データ構造だと、e.key0
はtrue
またはundefined
になります。
例えばelem.classList.toggle('className', e.key0)
としたい場合などで、e.key0
の値をtrue
またはfalse
にしたいなら、最低限以下のデータ構造にしないといけません。
const MY_ENUM = {
'key0':{'key0':true,'key1':false,'key2':false,'key3':false,/*...*/},
'key1':{'key0':false,'key1':true,'key2':false,'key3':false,/*...*/},
'key2':{'key0':false,'key1':false,'key2':true,'key3':false,/*...*/},
'key3':{'key0':false,'key1':false,'key2':false,'key3':true,/*...*/},
// ...
};
データ構造を作成する関数を作ることができます。
以下は最低限の列挙型的データ構造を作成する場合。
const makeEnum = keys=>{
const m = {};
for (const k of keys.split(' ')) {
m[k] = Object.freeze({[k]:true,});
}
return Object.freeze(m);
};
// ...
const MY_ENUM = makeEnum('key0 key1 key2 key3');
// ...