JavaScriptの動かないコード(中級編)正規表現をwhile内で定義すると無限ループで固まるエラー (execでグローバルなマッチだと,処理がフリーズ)
以下のJavaScriptコードが,意図した動作をしないのは,なぜですか。(制限時間1分)
やりたい事:
- 複数の文字列がある。
- それぞれの文字列から,URLのトップレベルドメイン(TLD)を全て抜き出す。
- 抽出のために,RegExp.exec() メソッドで,正規表現にグローバルオプションを付けて実行する。
<script> // 検索対象の文字列たち var strs = [ "URLは,http://a.com/ と,https://b.jp/ です。よろしくね。", "どうぞhttp://c.com/においで下さい。", "http://d.jp/ から移転しました。こちら→https://e.info/ " ]; /* マッチするすべてのTLDを列挙 */ // 検索対象のすべての文字列を,順番に検査する。 for( var i = 0; i < strs.length; i ++ ){ // この一つの文字列の中に含まれる // 全てのTLDを抽出。 var str = strs[i]; // execメソッドが値を返し続ける限り, // whileでループを回し続ける。 var arr; while( ( // execの結果は毎回,配列として受け取る。 arr = ( // 正規表現にgオプションを付け, // 文字列内で複数回マッチさせる。 /https?:\/\/[^\/]+\.([^\.\/]+)/g ).exec( str ) ) != null ){ // 括弧でキャプチャした文字列を表示 alert( "トップレベルドメインは" + arr[1] ); } } </script>
発生する不具合
JavaScriptの動かないコード(中級編) 正規表現の括弧キャプチャを,グローバルで繰り返しmatchできない (gオプションを付けると部分文字列の抽出が無効)
以下のJavaScriptコードが,意図した動作をしないのは,なぜですか。(制限時間1分)
やりたい事:
- (試行1)では,文字列からトップレベルドメインを1つだけ抽出する。
- これは上手くいく。
- (試行2)では,文字列からトップレベルドメインを全て抽出する。
- これは正常に動作しない。なぜなのか。
<script> // 元の文字列 var str = "URLは,http://a.com/ と,https://b.jp/ です。よろしくね。"; /* (試行1) 正規表現にgオプションを付けず, 情報を1個だけ抽出してみる。 */ // トップレベルドメインを抜き出す。 var m; m = str.match( new RegExp( "https?://[^\\/]+\\.([^\\.\\/]+)/" ) ); // httpとhttpsの両方に対応。 // ドメイン名の最後の部分だけを,カッコで抜き出す。 // つまり,ドメイン中の最後のドット以降の文字列を抜き出す。 // 配列の0番目には,マッチした文字列全体が入っている。 //alert( m[0] ); => "http://a.com/" // 配列の1番目には,括弧でキャプチャした部分が入っている。 alert( "トップレベルドメインは" + m[1] ); // => "com" /* (試行2) 正規表現にgオプションを付けて, マッチした情報を全て抽出してみる。 */ // 正規表現にgオプションを付ける。 m = str.match( new RegExp( "https?://[^\\/]+\\.([^\\.\\/]+)/", "g" ) ); // 括弧でキャプチャした部分を2つとも表示。 alert( "1つ目にマッチしたトップレベルドメインは" + m[1] ); alert( "2つ目にマッチしたトップレベルドメインは" + m[2] ); </script>
発生する不具合
JavaScriptの動かないコード(中級編) forループ内でイベントリスナを定義したら,動作がおかしい。(クロージャや関数オブジェクトの性質を理解していないために発生するエラー)
以下のJavaScriptコードが,意図した動作をしないのは,なぜですか。(制限時間1分)
やりたい事:
・ボタンごとに,0, 1, 2 という異なる数を表示したい。
<h3>ボタンごとに異なる数字をアラート表示するサンプル</h3> <input type="button" id="id0" value="0"> <input type="button" id="id1" value="1"> <input type="button" id="id2" value="2"> <script> for (var i = 0; i < 3; i ++ ){ // クリック時のイベントを定義 document.getElementById( 'id' + i ).onclick = function(){ // それぞれ異なった数値を表示する。 alert( i ); }; } </script>
解答は下記の通り。
続きを読む