【JavaScript】文字列の配列で正規表現にマッチするものを含むか判定する方法

以前に書いた[【JavaScript】文字列の配列で正規表現にマッチするものだけを取り出す方法](https://qiita.com/mascii/items/0a505698a9e5b7c70d93)という記事では、`bind`メソッド (`Function.prototype.bind`[^1])とビルトイン関数をうまく活用した例を紹介したつもりのですが、後日その例が良くないこと(`bind`なしでかつ可読性も高い書き方があった)に気付きました。
その後も`bind`メソッドをうまく活用した例を考えた続けていたところ、今度こそ(?)は良い例を見つけました。

今回は`Function.prototype.bind`[^1], `Array.prototype.some`[^2], `RegExp.prototype.test`[^3]を組み合わせ、標題のことを実現する例を紹介します。

# サンプル
## まずは`bind`なしで
Node.jsでは`process.argv`によって、コマンドライン引数が格納された配列(正確には3番目の要素から格納される[^4]ので、`process.argv.slice(2)`)を受け取ることができるので、これを用いた例を紹介します

```js:test01.js
const hasVersion = process.argv.slice(2).some(RegExp.prototype.test, /^(-v|--version)$/i);
console.log(hasVersion);
```

これは、コマンドライン引数に`-v`または`--version`が指定された場合に`true`, 指定されなかった場合に`false`を表示する例となっています。
正規表現にフラグ`i`(大文字小文字の区別なし)を指定しているので、例えばコマンドライン引数に`-V`が指定された場合にも`true`が表示されます。

実行結果は以下の通りです

```bash
$ node test01
false
$ node test01 -v
true
$ node test01 -V
true
$ node test01 --version
true
$ node test01 --readonly --VERSION
true
```

## `bind`登場
`-v`または`--version`の有無の判定の他に、`-ro`または`--readonly`の有無の判定もしたいといったケースも考えられると思います。
引数に正規表現を指定すると、コマンドライン引数にマッチするものがあるか判定する関数があると便利そうです。
以下の例では `checkArgs` がそのような関数となっていて、`bind`を用いて生成されています。

```js:test02.js
// const checkArgs = Array.prototype.some.bind(process.argv.slice(2), RegExp.prototype.test);
const checkArgs = [].some.bind(process.argv.slice(2), /./.test);

console.log('Version:', checkArgs(/^(-v|--version)$/i));
console.log('ReadOnly:', checkArgs(/^(-ro|--readonly)$/i));
```

`[]`と`/./`は、`Array.prototype.some`と`RegExp.prototype.test`を呼び出すためだけにあるリテラルとなっています(詳しくは[以前に書いた記事](https://qiita.com/mascii/items/0a505698a9e5b7c70d93)を参照)

実行結果は以下の通りです

```bash
$ node test02
Version: false
ReadOnly: false
$ node test02 -v
Version: true
ReadOnly: false
$ node test02 -ro -v
Version: true
ReadOnly: true
$ node test02 --readonly --VERSION
Version: true
ReadOnly: true
$ node test02 --version --ReadOnly
Version: true
ReadOnly: true
$ node test02 --version -Ro
Version: true
ReadOnly: true
```

また、`const`宣言を除けばECMAScript 6以上の仕様は使っていないので、Internet Explorer 11でも動作しました。

IE11のコンソール上での実行例

```js
var checkArgs = [].some.bind(['Red', 'Green', 'Blue', 'White'], /./.test);
checkArgs(/^White$/i);
checkArgs(/^R/i);
checkArgs(/Black/i);
```

実行結果は以下の通りです

![ie11_some_bind_regexp.png](https://qiita-image-store.s3.amazonaws.com/0/137045/4b814f84-1acd-ea41-2405-05695b83c9bb.png)

# 配列の`indexOf`, `includes`メソッドよりも良いところ
今回紹介した方法が`indexOf`メソッド(`Array.prototype.indexOf`[^5]), `includes`メソッド(`Array.prototype.includes`[^6])と比べて良いところをまとめました

* 大文字小文字の区別をしない指定(フラグ`i`)やOR検索といった正規表現の機能を利用できる
* ECMAScript 5までの仕様のみ利用している
    * `includes`メソッド(特定の要素が配列に含まれているかどうかを真偽値で返す[^6])はES5までに入っていない

# 参考文献
[^1]: [Function.prototype.bind() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)
[^2]: [Array.prototype.some() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/some)
[^3]: [RegExp.prototype.test() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test)
[^4]: [Node.jsでコマンドライン引数を取得する - Qiita](https://qiita.com/furusin_oriver/items/f030d1eaa9e7b54233c3)
[^5]: [Array.prototype.indexOf() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf)
[^6]: [Array.prototype.includes() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/includes)