JavaScript
Node.js
正規表現

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

More than 1 year has passed since last update.

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

今回はFunction.prototype.bind1, Array.prototype.some2, RegExp.prototype.test3を組み合わせ、標題のことを実現する例を紹介します。

サンプル

まずはbindなしで

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

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が表示されます。

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

$ 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を用いて生成されています。

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.someRegExp.prototype.testを呼び出すためだけにあるリテラルとなっています(詳しくは以前に書いた記事を参照)

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

$ 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のコンソール上での実行例

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

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

ie11_some_bind_regexp.png

配列のindexOf, includesメソッドよりも良いところ

今回紹介した方法がindexOfメソッド(Array.prototype.indexOf5), includesメソッド(Array.prototype.includes6)と比べて良いところをまとめました

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

参考文献