appendChildの挙動について教えて下さい。【JavaScript】
プログラミング初心者です。
documentオブジェクトのappendChildメソッドは、
「追加するノードが既にdocument内に存在するノードの参照であった場合、
もともとあった方を削除してから追加する」
そして
「document内に同じノードが2個以上存在できない」
そうですが、
appendChildおよびdocumentは何をもって、
『もともとdocument内に存在するノードA』
と
『新しく追加しようとしているノードA'』
が同じものである
と判断しているのかわかりません。
###実際に困っていること
html+JavaScript+CSSで、以下のようなプログラムを作っているのですが、
挙動がうまくいきません:
〈要件定義〉
・黄色の背景のdiv領域(id="wrapper")に
** 赤色の小さなdivの箱(class="hako")を**
** 一定時間毎(2秒)に無限増殖させる。**
・スタートボタンを押すと、赤いdiv箱が出現して増殖を開始し、
** 放っておけば2秒ごとに領域内にdiv箱が一つずつ生成される。**
〈問題点〉
・ボタンを押しても、div箱は、見た感じは初めの一個しか生成されない。
・開発者ツールを見ると「一応、div箱は2秒ごとに生成されてはいる」と思われる。
・原因はおそらく、上記のappendChildの仕様により、生成する毎に元あった箱が削除されているのではないか、と思われる
以下が、問題のコードになります。
### コード
OSはWindows10、ブラウザはchromeです。
【html】
html
1<!--<!DOCTYPE html> 2DOC宣言を書くと、互換モードから標準モードになり、 3styleに不具合が生じる!これから書かない! 4--> 5<html lang="ja" dir="ltr"> 6 <head> 7 <meta charset="utf-8"> 8 <link rel="stylesheet" type="text/css" href="zoushoku.css"> 9 <script src="zoushoku.js" charset="utf-8"></script> 10 <title>増殖(オブジェクト指向的)</title> 11 </head> 12 <h1>増殖(オブジェクト指向的)</h1> 13 <body> 14 下のボタンを押すとボックスが生まれます。 <br> 15 一定時間ごとに増殖します。 <br> 16 <button id="startBtn" name="startBtn" type="button">start</button><br> 17 <div id="wrapper" class="clearfix"></div> 18 </body> 19</html> 20
【css】
css
1@charset "UTF-8"; 2/*.clearfix:after{ 3 content:""; 4 display:block; 5 clear:both; 6} 7*/ 8#wrapper{ 9 width:500; 10 height:500; 11 background-color: yellow; 12} 13 14.hako{ 15 width: 30; 16 height: 30; 17 background-color: red; 18} 19
【JavaScript】
javascript
1window.onload = function() { 2 3 /*増殖するhakoの設計図*/ 4 var hako = document.createElement("div");//新しいdivエレメントを生成 5 hako.className = "hako";//class名はhako 6 7 /*hakoが住んでいるdivエレメント領域をwrapperとする。*/ 8 var wrapper = document.getElementById("wrapper"); 9 10 /*hakoの増殖関数*/ 11 function zoushoku(){ 12 setInterval(function(){wrapper.appendChild(hako)},2000); 13 };//こうして関数宣言によってラッピングしてやれば、setIntervalは勝手に実行しない。 14 var start = document.getElementById("startBtn");//増殖スタート 15 start.addEventListener("click", zoushoku); 16 17};
原因の検討はついたものの
私の仮説が正しければ、
「appendChildによって、毎回(2秒ごとに)、ノードの追加の前に、ノードの削除が行われている」
つまり、
「同じファイル名のファイルを作成するとき、もともとあるファイルを削除してから作成する」
みたいなことがされている、ということなので、
追加するdiv箱のプロパティを調整することが必要なのではないかと思いました。
しかし、appendChildが何をもって、
「もともとdocument内にあるdiv箱と、これから追加しようとしているdiv箱が同じ」
と判断しているのか、調べても分からないので、対処の仕方がわかりません。
「classNameが重複しているのがいけないのか」と一瞬思いましたが、
class名はidとは違って個体識別子ではないので、そこを疑うのは不自然だと思いました。
あと考えられることといったら、
「JavaScript、HTMLの言語処理系の仕様により、
HTMLドキュメント内のDOMと、JavaScriptのスクリプト内の変数が、
同期されてしまっている」
というところでしょうか?
そこらへんの言語処理系の仕組みについてはあまり勉強が進んでいないので、対処の仕方がわかりません。
どう思われますか?ご回答宜しくお願いします。
###追記
ベストアンサーにとても迷いましたが、今回は、
問題の核心的な部分を理解する糸口を最初に示して頂いたmaisumakun様をベストアンサーにさせて頂きたいと思います。
他の皆さまも、とても参考になりました!ご回答ありがとうございました!
最後に、修正したjsのコードを這っておきます。
setInterval毎にcreateElementを発動するように、createElementのところもzoushoku(){}の内部に包んでやりました。
javascript
1window.onload = function() { 2 3 4 /*hakoが住んでいるdivエレメント領域をwrapperとする。*/ 5 var wrapper = document.getElementById("wrapper"); 6 /*hakoの増殖関数*/ 7 function zoushoku(){ 8 /*増殖するhakoの設計図*/ 9 /*createElementは同じ宣言から生まれたオブジェクトは同じものとみなされ、 10* appendCHild標準機能である「同一オブジェクトの追加時には元のものを削除」 11が発動してしまうため、この関数の内部に記述して、 12次から次へとcreateElementを宣言しなおさなければならない。 13そうすることで、「別々のcreateElement」から「別々のオブジェクト」がちゃんと生成される*/ 14 var hako = document.createElement("div"); 15 hako.className = "hako";//class名はhako 16 wrapper.appendChild(hako);//子ノードリストにノードを追加 17 };//こうして関数宣言によってラッピングしてやれば、setIntervalは勝手に実行しない。 18 var start = document.getElementById("startBtn");//増殖スタート 19 start.addEventListener("click", function(){ 20 setInterval(zoushoku,2000) 21 }); 22 23}; 24

回答7件
あなたの回答
tips
プレビュー