前の記事で if式 じゃなくて、if関数は作ってしまったのだ。
こちらの記事です。
JavaScriptの三項演算子が読みにくいらしいので、if式ならぬ if関数を作りました。そしてもっと読みにくい感。 - Qiita
https://qiita.com/standard-software/items/794724427fcee1cbd00b
どうせif関数も作ったので、真似て switch関数を作ります。
名前は「switch_」です。
値を渡したら、それを評価して分岐するという機能。
こんな書き方ができるようになります。
var switchValue = 1;
console.log(
switch_(switchValue)([
[1, 'Val1'],
[2, 'Val2'],
[3, 'Val3'],
['1', 'ValStr1'],
['defaultVal']
])
);
var switchValue = '1';
console.log(
switch_(switchValue)([
[1, 'Val1'],
[2, 'Val2'],
[3, 'Val3'],
['1', 'ValStr1'],
'defaultVal'
])
);
特定条件によって値を代入するときに let 変数じゃなくて const 変数を使いたい場合でも、この「switch_関数」を使えば使い放題です。(使わなくても工夫したら使いたい放題だろうけれどもな)
上の書き方、細かくみてみるとわかるように、配列じゃない値を渡したり、長さ1の配列を渡すとそこがデフォルト値になります。
数値の1と、文字列の1の比較もできるぞ、という感じ。
なぜ配列にしているかというと、オブジェクトだと、{1: 'Val1', '1': 'ValStr1'} こんな書き方ができないから。オブジェクトのプロパティは全部文字列に変換されるらしいよ。
「switch_」関数の実装
ということで実装です。結構簡単。
const isFunction = (value) => {
return (typeof value === 'function');
};
const functionValue = (value) => {
if (isFunction(value)) {
return value();
} else {
return value;
}
};
const assert = function (value, message) {
if (typeof message === 'undefined' || message === null) {
message = '';
}
if (value !== true) {
throw new Error(message);
}
};
const switch_ = (expression) => {
return (args) => {
assert(Array.isArray(args), 'switch_ function');
for (let i = 0; i < args.length; i += 1) {
if (!Array.isArray(args[i])) {
return args[i];
} else if (args[i].length === 0) {
return undefined;
} else if (args[i].length === 1) {
return args[i][0];
} else {
if (args[i][0] === expression) {
return functionValue(args[i][1]);
}
}
}
};
};
if_関数の実装と同じように、内部で、functionValue を使っているので、次のように書けば、条件合致しない部分のものは、関数呼び出しそのものが行われません。
これで場合によっては、値によって関数呼び出しを制御する、ということも簡単にできます。
var switchValue = 2;
console.log(
switch_(switchValue)([
[1, _=>'Val1'],
[2, _=>'Val2'],
[3, _=>'Val3'],
['1', _=>'ValStr1'],
'defaultVal'
])
);
switch_関数は、if_関数よりかはいくらか実用的かもしれないですね。
まあ、これもお遊びみたいなものですが、こんなこともできる。ってことで。よろ。
追記
2019/03/21(木)
switch_ を組み込んだライブラリを npm で配信しています。TypeScriptコードです。
standard-software/copipejs: simple code parts
https://github.com/standard-software/copipejs
デフォルト値の記載方法を少し変えました。
https://github.com/standard-software/copipejs/blob/master/source/copipe_core.ts
このあたりのソースをみると実装がわかり、
https://github.com/standard-software/copipejs/blob/master/source/test/test_copipe_core.ts
こちらのテストコードをみると使い方がわかります。