練炭ブログ

萌え壁紙、Irvine、DMonkey、Proxomitron などの情報を扱ってます。

DMonkey: String/RegExp.replace で0回のマッチをキャプチャすると number 0 になる

コメントなし»

[4月29日追記] 訂正: number 0 になるのではなく、キャプチャ結果が引数として渡されないため、マッチした位置(index)を参照していただけでした(0回のマッチと1回以上のマッチの場合で arguments.length が違う)。申し訳ありません。

  • String.replace() や RegExp.replace で、
  • 正規表現に (~)?(~)* を使い、
  • 置換文字列として関数を指定していると、
  • 最後のキャプチャ部分が0回の繰り返しにマッチした時、
  • キャプチャ結果として関数の引数に number 型の 0 が渡される。キャプチャ結果が関数の引数に渡されない。

通常は空文字列が渡されるのですが、上記のように最後のキャプチャが0回マッチだと 0 が渡されますキャプチャ結果が渡されません。他の文字列と + 演算子で繋げたりすると '0' という文字列として扱われてしまうので注意が必要です。

alert (
  'ab'.replace (/a(\d)?b/, function (s, p1) { return typeof p1; })
);
//number

alert (
  'ab'.replace (/a(\d)*b/, function (s, p1) { return typeof p1; })
);
//number

なお、各種ブラウザでは0回マッチでもキャプチャ結果が引数として渡されますが、その内容は Firefox 12 では空文字列(string)、Internet Explorer 8 と Google Chrome 18 では undefined になります。

常に文字列で渡される Firefox 形式が楽だと思うのですが、ECMAScript 的にはどの動作が正しいんでしょうか?

対処法

  • 正規表現の末尾に () を付ける。
  • (~)?((~)?) のように外側をキャプチャする。
  • 置換文字列として指定された関数内で、number 型か調べて空文字列に置き換える。

一つ目の方法の例。

alert(
  'ab'.replace(/a(\d)?b()/, function (s, p1) { return typeof p1; })
);
//string

alert(
  'ab'.replace(/a(\d)*b()/, function (s, p1) { return typeof p1; })
);
//string

DMonkey: URL オブジェクトの各プロパティ内容

コメントなし»

URL オブジェクトの各プロパティが実際にどのような内容になるか調べてみました。

空文字列以外はクオートを省略してあります。

var u = new URL ('http://example.com:8080/dir/index.html?q=1#frag');
alert ([
  u.url,       // http://example.com:8080/dir/index.html?q=1#frag
  u.protocol,  // http
  u.host,      // example.com:8080
  u.hostname,  // example.com
  u.port,      // 8080
  u.path,      // /dir/index.html?q=1#frag
  u.directory, // /dir/
  u.filename,  // index.html
  u.query      // ?q=1#frag
].join ("\n"));

最小限の構成要素だと以下のようになります。

var u = new URL ('https://example.com/');
alert ([
  u.url,       // https://example.com/
  u.protocol,  // https
  u.host,      // example.com
  u.hostname,  // example.com
  u.port,      // ''
  u.path,      // /
  u.directory, // ''
  u.filename,  // ''
  u.query      // ''
].join ("\n"));