読者です 読者をやめる 読者になる 読者になる

JavaScriptで/.*/()とは何か.

JavaScript

最初に, 皆さんにブラウザーのコンソールで/.*/()を試していただきたい.

そして, 他のタブとか色々試して欲しい.

どんな文字が返ってきましたか?

多分一意じゃないはず. バラバラ. ワケが分からないよ.

そこで, このエントリーを思い出した.

(前にも見たことあった...)

typeof演算子から学ぶJavaScriptのデータ型の概念と関係する考察のまとめ(id:sandai)

「というわけでデフォルトでexecメソッドが呼び出されるようになっています。」

そうなのか...execなのか.

ECMA-262のどこに書いてるのかは分からないけど(←あ...)

まあいいや.

/.*/.exec()ってなることは分かった.

....function is not a functionの解説はこのエントリーに任せるとして...

.execに引数がない場合どうなるのか?

挙動から見てみて明らかに...

RegExp.inputが用いられています!!!!!


ちょいとテスト

/home/itchyny$ node
> RegExp.input
''
> /a+/.exec()
Error: No input to /a+/
at RegExp.exec (native)
at [object Context]:1:6
at Interface.<anonymous> (repl.js:150:22)
at Interface.emit (events.js:42:17)
at Interface._onLine (readline.js:132:10)
at Interface._line (readline.js:387:8)
at Interface._ttyWrite (readline.js:564:14)
at ReadStream.<anonymous> (readline.js:52:12)
at ReadStream.emit (events.js:59:20)
at ReadStream._emitKey (tty_posix.js:286:10)
> RegExp.input = 'a aa aaa'
'a aa aaa'
> /a+/.exec()
[ 'a', index: 0, input: 'a aa aaa' ]
> RegExp.input = ''
''
> /a+/.exec()
null

ホラネ.

.exec()の返り値はArrayのインスタンスだけど,

index, input, lengthの値がDefineOwnPropertyされるんだな〜

(とECMA-262 5thを見ながら)

RegExp.inputは代入できる...!!!!

.oO(あれ... なんで最初, RegExp.inputはundefinedじゃないんだろう)

という訳で(いろんな疑問があるけど), タイトルに対する答えは

/.*/.exec(RegExp.input)でした. ちゃんちゃん♬

RegExp.inputってのは前にexecやらtestやらやったときに

テストしたStringの事ね.

JavaScript Regular Expressionsを見てみるとRegExp.inputはRegExp.$_とも書けるって書いてる.

Perlなんだね! (そう言えばECMA-262の15.10の最初にそんなこと書いてあったような...)

((((いろいろ調べててES3のRegExpの変なところを見た気がするけどそれはいいや....

ところでtypeof /./は'function'なんだから(V8で),

もうyou, 関数になっちゃいなヨ!!!

> f = /a+/g
/a+/g
> f('a aa aaa aaaa aaaaa')
[ 'a', index: 0, input: 'a aa aaa aaaa aaaaa' ]
> f()
[ 'aa', index: 2, input: 'a aa aaa aaaa aaaaa' ]
> f()
[ 'aaa', index: 5, input: 'a aa aaa aaaa aaaaa' ]
> f()
[ 'aaaa', index: 9, input: 'a aa aaa aaaa aaaaa' ]
> f()
[ 'aaaaa', index: 14, input: 'a aa aaa aaaa aaaaa' ]
> f()
null
> f()
[ 'a', index: 0, input: 'a aa aaa aaaa aaaaa' ]
> f()
[ 'aa', index: 2, input: 'a aa aaa aaaa aaaaa' ]
> f()
[ 'aaa', index: 5, input: 'a aa aaa aaaa aaaaa' ]


無限イテレータ(itertools.cycle)になるんじゃないか?

> g = /./g
/./g
> s = '     '
'     '
> i = 20; while(--i) { g(s); console.log(g.lastIndex); }
1
2
3
4
5
0
1
2
3
4
5
0
1
2
3
4
5
0
1

(lastIndexはRegExpではなくて正規表現オブジェクトに

束縛されてるから他の正規表現の操作が入っても, 大丈夫なはず)

最後に...

おい!!! 正規表現FizzBuzzするなし!!!

var f=/./g,g=/./g,i=0;while(i++<100)console.log((f('  ')?'':'Fizz')+(g('    ')?'':'Buzz')||i)

追記

実装が変わりました.

関数呼び出しみたいに正規表現を使えなくなりました.

取り敢えずFizzBuzzだけ変更しとく.

var f=/./g,g=/./g,i=0;while(i++<100)console.log((f.exec('  ')?'':'Fizz')+(g.exec('    ')?'':'Buzz')||i)