フロントエンドド素人が、JavascriptでDOM操作をして、子要素を消そうとしてあれ？ってなった話

## はじめに

SQLの実行結果によって、HTML要素を削除したり、追加しているときに気づいた話を自分用メモとして残します。
もしかしたら**勘違いしていることがあるかもしれないので、その際にはご指摘いただけると幸いです。**

早速ですが以下の例、なんで子要素、つまり「太郎元気です！」が削除されず、どう消すのかわかりませんでした。

#### 【HTML構成】
```HTML
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <h2>元気ですか～！</h2>
    <div id="parentObj">
      <p id = "childObj">太郎元気です！</p>
      <p id = "nextChildObj">二郎元気です！</p>
    </div>
  </body>
</html>
```

#### 【Javascript構成】
```JavaScript
const getParentObj = document.getElementById("parentObj");
const getChildObj = document.getElementById("childObj");

if(getParentObj.removeChild(getParentObj.firstChild)){
  alert("削除成功"); // 条件文は通るが、実際に太郎元気です！は消されてない。
}
else{
  alert("削除失敗");
}
```

直接子要素にアクセスしてやれば話は早いですが、子要素にidが振られていなかったときに大変です。
適当にwhile文を回して全部消して、削除したくない子要素だけ復活させるなんてやったら手間ですし、無駄な処理です。


## 結論

はじめに、でお話したHTML構成だと、直接子要素指定する or whileで全削除からの必要子要素のみ復活以外の方法では、以下のようにするしかないと思います。

```JavaScript
const getParentObj = document.getElementById("parentObj");
const getChildObj = document.getElementById("childObj");
const childCount = getParentObj.childElementCount;

for(var i = 0; i < childCount; i++){
  getParentObj.removeChild(getParentObj.firstChild);
}
```


## 具体的説明

しかし、以下の例で条件文が通ってしまうことに違和感があり、原因を探ったところわかりました。

```JavaScript
const getParentObj = document.getElementById("parentObj");
const getChildObj = document.getElementById("childObj");

if(getParentObj.removeChild(getParentObj.firstChild)){
  alert("削除成功"); // 条件文は通るが、実際に太郎元気です！は消されてない。
}
else{
  alert("削除失敗");
}
```

### 消えてないのではなく、消える対象を勘違いしているだけ

以下の例、本当は消す対象がないだけで、実行的にはうまくいっているんです。

```JavaScript
const getParentObj = document.getElementById("parentObj");
const getChildObj = document.getElementById("childObj");

if(getParentObj.removeChild(getParentObj.firstChild)){
  alert("削除成功"); // 条件文は通るが、実際に太郎元気です！は消されてない。
}
else{
  alert("削除失敗");
}
```

というのも、HTML構成を少し変化させてみてみます。


#### 【変化後のHTML構成】
```HTML
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <h2>元気ですか～！</h2>
    <div id="parentObj">
      三郎だって元気だよ。
      <p id = "childObj">太郎元気です！</p>
      <p id = "nextChildObj">二郎元気です！</p>
    </div>
  </body>
</html>
```

#### 【Javascript構成】
```JavaScript
const getParentObj = document.getElementById("parentObj");
const getChildObj = document.getElementById("childObj");

if(getParentObj.removeChild(getParentObj.firstChild)){
  alert("削除成功"); // 条件文は通り、三郎だって元気だよ。が削除されました！
}
else{
  alert("削除失敗");
}
```


ここで、親要素の内部に書かれた情報だけ削除されているのが、ブラウザのコンソールなどで調べればお分かりいただけると思います。

つまり、removeChild(getParentObj.firstChild)は、いきなり子要素に着目するのではなく、親要素を参照した後に、子要素のアクセスをしていることがわかりました。


## おまけに

以下のようにやると、idが付けられていない要素の削除もできます。


#### 【おまけのHTML構成】
```HTML
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <h2>元気ですか～！</h2>
    <div id="parentObj">
      <p>太郎元気です！</p>
      <p>二郎元気です！</p>
    </div>
  </body>
</html>
```
#### 【おまけのJavascript構成】
```JavaScript
if(getParentObj.removeChild(getParentObj.firstElementChild.nextElementSibling)){
  alert("削除成功"); // 条件文は通り、二郎元気です！が削除されました！
}
else{
  alert("削除失敗");
}
```

## 最後に
すごく単純作業ですが、これに小一時間近くとられたので、メモしました。
removeChildの動きをしっかり理解することが大切ですね。

### 参考
- Node.removeChild
https://developer.mozilla.org/ja/docs/Web/API/Node/removeChild
- ライブラリを使わない素のJavaScriptでDOM操作
https://qiita.com/kouh/items/dfc14d25ccb4e50afe89