JavaScriptの動かないコード (初級編) DOM要素の配列を,forループで順番に全削除できない
以下のJavaScriptコードが意図した動作をしないのは,なぜですか。(制限時間1分)
やりたい事:
- DOM操作により,div要素を全て削除する。
<body> <input type="button" value="DIV要素の削除を実行" onclick="f()"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <script> function f() { // 全要素を取得 var arr = document.getElementsByTagName("div"); for( var i = 0; i < arr.length; i ++ ) { var elem = arr[i]; // 一つずつ削除 elem.parentNode.removeChild(elem); } } </script> </body>
発生する問題
実行するたびに,全体のおよそ半分の要素が,削除されずに残ってしまう。
5つの要素がある場合は,3回削除するとすべて削除し終わる。
forループで全ての要素を削除しきれていない。
問題の原因と解決策
1つの要素を削除するたびに,後ろの要素が頭にずれこんできて,配列の長さが変わってしまう事が原因。
1つの要素をremoveChildすると,消えた分のインデックスに対して,その次の要素が入り込んでくるのだ。
だから,インデックスを頭から順番にスキャンするようなループだと,削除されずに要素が残ってしまう。
これを解決するには,forループをDOM要素のリストの後ろから(逆から)削除してゆけばよい。
for( var i = 0; i < arr.length; i ++ ) ↓ for( var i = arr.length - 1; i >= 0; i -- )
これでOK。末尾から全要素を削除できる。
この現象は,Arrayのsplice()では発生しない。
普通の配列であれば,splice()で指定したインデックスの要素を削除しても,要素はundefinedになるだけ。
だから,消えた分の項目に後ろがずれこむ事はない。
下記のコードは安全に動作する。
<input type="button" value="実行" onclick="f()"> <script> function f() { var arr = [2,4,6,8,10]; for( var i = 0; i < arr.length; i ++ ) { arr.splice( i ); } alert( arr.length ); // 0 alert( arr.join(",") ); } </script>
JavaScriptの配列の要素を削除する(delete演算子とspliceメソッド) | 山本隆の開発日誌
http://www.gesource.jp/weblog/?p=4112
getElementsByTagName parentNode.removeChild | JavaScriptのQ&A【OKWave】
http://okwave.jp/qa/q4620142.html
- gg[0]をremoveすると、今までgg[1]だったオブジェクトがgg[0]に 格上げされます。 なのでループでgg[1]を削除するとそれはそれまでgg[2]だったものです その流れでひとつ置きに削除されていくわけです。 なので、この手の処理はけつから消していきます。
Javascriptの話。 :: ウェブデザイナーの日記
http://blog.3ot.net/design/javascript...
- var num = e.childNodes.length; for(var i = 0; i < num; i++){ e.removeChild(e.firstChild); } }
- e.childNodes.lengthでノード数を取得できるけど、そのままforの中に入れるんじゃなくて、変数に代入してからだとうまくいく
関連する記事:
JavaScriptの動かないコード (中級編) iframe内のDOM要素を別フレームにコピーできないエラー
http://language-and-engineering.hatenablog.jp/entry/20090214/p1
JavaScriptの動かないコード (中級編) innerHTMLを追記するとイベントハンドラが消える
http://language-and-engineering.hatenablog.jp/entry/20090903/p1
JavaScriptの動かないコード (中級編) cloneNodeで選択状態が変わるエラー
http://language-and-engineering.hatenablog.jp/entry/20080926/1222365534