Dec 29, 2005
Safariでreplace callback のエミュレーション
replaceメソッドをhackしてsafariでもreplace callbackを使えるようにしてみた。Safari バージョン 2.0.2(416.13)で上手く動いたそうです。手元に環境が無いので細かい検証はできませんが、とりあえず。http://la.ma.la/misc/js/replace_callback/
解説
JavaScriptのString#replaceメソッドは文字列を置換して新しい文字列を返すメソッドですが、第二引数に置換後の文字列を指定する代わりにfunctionオブジェクトを渡してやると、Perlでいうところのeオプションみたいなことができます。
// 大文字を小文字に、小文字を大文字に
String.prototype.swapcase = function(){
return this.replace(/([a-z])|([A-Z])/g,function($0,$1,$2){
return ($1) ? $0.toUpperCase() : $0.toLowerCase()
})
}
"Hello World!!".swapcase() // hELLO wORLD!!
第一引数にはマッチ文字全体、それ以降には後方参照用にカッコで囲った部分が渡されます。その後にはマッチ箇所の先頭からのoffset値、String全体が渡されます(ここでは使ってません)
// 少しわかりやすく書くと
String.prototype.swapcase = function(){
var reg = /([a-z])|([A-Z])/g;
var callback = function(match_text,lower,upper,index,self){
return (lower) ? lower.toUpperCase() : upper.toLowerCase()
};
return this.replace(reg, callback)
}
こんな感じになります。単純な置換だけではなくて、文字列の出現頻度を調べたりとか、簡単なテンプレートシステムを組んだりすることもできます。
// Ruby風の変数展開
String.prototype.fill = function(param){
return this.replace(/#\{(.*?)\}/g,function($0,$1){
return (param[$1] != undefined) ? param[$1] : ""
})
}
"My name is #{name}.".fill({ name : "John" }) // My name is John
で、これを知ってからゴリゴリ使ってるのですが、どうもSafariでは使えないという話らしく
http://jszen.blogspot.com/2005/12/safari-and-stringreplace-method.html
次のリリースで直るそうですが、直ったところで古いバージョン使ってる人はいるわけなので作ってみました。本来のreplaceメソッドより動作は遅いはずなのでsafariの場合だけ適用するのが良いです。
いくらなんでもsafari酷いなあ、と思ってたのですが、互換性を気にして便利なものを使えないよりは、自前で実装しまったほうが楽なケースも多いんじゃないかと。
ブラウザの差異は大体こういう方法で吸収できるはず。
参考
ECMA-262 3rd Edition 邦訳 String.prototype.replaceのところhttp://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/15-5_String_Objects.html#section-15.5.4.11
正規表現のeオプションをJavaScriptでエミュレート
http://hail2u.net/blog/coding/emulate_regexp_e_option_in_js.html
Edit this entry...
wikieditish message: Ready to edit this entry.
A quick preview will be rendered here when you click "Preview" button.