5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScript で if式っぽく動くようなswitch式...というかswitch関数作ったよ。

Last updated at Posted at 2018-12-09

前の記事で 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
こちらのテストコードをみると使い方がわかります。

5
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?