前提
JSで文字列の一部をパターン指定で抽出する際、matchメソッドを用いる。
このmatchメソッドの返り値は以下の2通り。
- マッチした場合 :
Array
- マッチしなかった場合 :
null
参考:String.prototype.match() - JavaScript - MDN Web Docs
やりたいこと
マッチ結果の配列ではなく、該当した文字列を直接取得したい。
とりあえず次のようなコードを書いた。
const result = 'abc123XYZ'.match(/[0-9]{3}/)[0] // '123'
しかし、文字列の中に指定パターンが存在せずマッチしなかった場合、null[0]のような形になってしまい、エラーになる。
TypeError: Cannot read properties of null
正直な記述
matchメソッドの返り値を一度仮の変数に格納し、ifで分岐する
const temp = 'abc123XYZ'.match(/[0-9]{3}/)
let result
if (temp) {
result = temp[0]
}
この解決方法はあんまりイケてない。
何度も使う場合には関数にして呼び出せばまだよいかもしれないが。
また、三項演算子を使うにしても、同じmatchメソッドを2度行うような形になってしまう。
そこで今回はよりスマートな記述方法は無いかなと考えてみた。
解決方法
01: オプショナルチェーン
const resultMatched = 'abc123XYZ'.match(/[0-9]{3}/)?.[0] // '123'
const resultUnmatched = 'abcXYZ'.match(/[0-9]{3}/)?.[0] // undefined
メリットは、ワンライナーで記述できる上、可読性を考えてもまあまあ。
また、キャプチャグループを使って抽出したい場合も添え字を[1], [2]と変えれば対応できる。
02: Null合体演算子
const [resultMatched] = 'abc123XYZ'.match(/[0-9]{3}/) ?? [] // '123'
const [resultUnmatched] = 'abcXYZ'.match(/[0-9]{3}/) ?? [] // undefined
オプショナルチェーンを使うよりも若干読みづらい?同じくらいか?
キャプチャグループを使う場合は[, result]
のように書く必要がある。
※読み手が左辺の宣言時点で認識できるよ、という言い分はあるかも?
最後に
ES20xxの新機能としてこれらの手法を知ってはいたものの、初めて実際にコードとして書くことができた。
その他もっと分かりやすいやり方がないかは検討します。