すがブロ

sugamasaoのhatenablogだよ

若手IT勉強会で「Secrets of the JavaScript Ninja」を読んできた(そして String#replace の凄さを知った!)

今回は7章の Regular expressions について

まず初めに

以下の若手IT勉強会では、jQueryの作者が贈るNinja本こと「Secrets of the JavaScript Ninja」を翻訳しつつ、読んできます。

次回の第22回の詳細は以下のページです。

参加申し込みはこっち

翻訳と言っても、事前になんとなく日本語約をする担当を決めて、当時はその人の翻訳した文章を頼りにするので、英語がわけわかんなくてもある程度はなんとかなると思います。
あ、ちなみに、下記から買えます。まだ本自体書き上がっていないので、適宜アップデートのお知らせがくるはずです(まだ一回しか来てないけど)。

閑話休題

正規表現についての話

ざっくり書くとこんな感じ

  • /hogehoge/ だと毎回正規表現オブジェクトがコンパイルされる(ブラウザによってはキャッシュしてくれるかもしれないけど、あてにしない方が良い)
  • そんな時は new RegExp でオブジェクトをキャッシュした方が良いよ
  • でも、execした後の参照のlastIndexが進んでしまう事には気をつけてね

という話とか、パフォーマンスに関して空白を取り除く(いわゆる trim メソッド)をどのように実装すると効率が良いかについて書いてあった。

そして本題

その他に、 replace メソッドについても詳しく書いてあった。レッシグ曰く「良く使う機能だよねHAHAHA」ということらしいのですが、私は初めて知りました。。。
例えば、replaceで単純な置換をする場合はこんな感じに書くかなと思うのですが

"hogehoge".replace(/^hoge/, "fuga")
// => "fugahoge"

で、そうじゃないんだ、マッチさせた '^hoge' に対してちょっとアレンジを加えたいんだよ、という場合も往々にしてあると思います。
上記の例で言うと、例えば '^hoge' の部分だけ強調させたい、とか。
そういう場合、2つの手段があります。どちらにも言えることですが、グルーピングと後方参照を使います。

第二引数に後方参照を使う

後方参照をそのまま使う場合。
replace関数の中でそのまま後方参照使えたんですね。知らなかったです。。。

"hogehoge".replace(/^(hoge)/, "[$1]")
// => "[hoge]hoge"

こんな感じでいわゆる後方参照がそのまま使用できます。ただし、その$1に対してメソッドを使う*1のような事はできないみたい*2なので、あまり凝ったことはできなそう。

第二引数にfunctionを使う

第二引数に function を渡すと、$0, $1... に該当する文字列が function の引数として受け取れます。

"hogehoge".replace(/^(hoge)/, 
    function(all, hoge){
        return "[" + hoge.toUpperCase() + "]"
    }
)
// => "[HOGE]hoge"
本書では

さらに発展させて replace メソッドの第二引数をうまく使ってURLにくっつくクエリストリングの圧縮とかをやっていた。

なんか知ってればスッゲー当たり前な感じがするけれど

個人的には「なんでこういう機能ないんだろうなー」と思っていたところだったので「そりゃあありますよねー」というメモとしてきちんと書いておくよ。
レッシグさんの含蓄はとても為になりますので、みなさんもぜひ参加すると良いですよ!

*1: $1.toUpperCase()

*2:よく調べてないです