JavaScript/jQuery初学者が一般のサンプルを読み解く時のポイント

jQuery初学者がつまづくポイントとして、**サンプルを見て「なんでそれで動くのか分からない」**、というのがあると思います。「jQueryでアコーディオンメニューを作りたい」と思ったとき、検索すればサンプルはたくさん出てきます。しかし、`セレクタ`は分かる、`on`で`イベントハンドラ`、など文法は分かっているのに、意味が分からない、自分で書ける気はしない、という感じです。

今回は、こちら↓のサイトで紹介されているアコーディオンを例に、jQueryの理解を深めるための、サンプルの**読み解き方**について書いてみたいと思います。

https://125naroom.com/web/3046

# 対象の読者
- JavaScript/jQueryの基本的な文法がわかる人。
- 一般のサイトでサンプルを見て、コピペして**動かすことはできるがなんで動くのか分からない**人。
- 分かるようになるためのコツが知りたい人。

# サンプルを読み解く流れ
ここでは以下のような流れでサンプルを読み解いていきます。
- サンプルのどこに着目して理解を深めたいか決める
- 関係ない部分を削る
- console.log()で処理の一部を取り出して確認する

１つ１つ見ていきましょう。

# サンプルのどこに着目して理解を深めたいか決める
上記サイトの「アコーディオン、シンプル版」を例に説明していきます。Codepenでサンプルが公開されています。サンプルそのままの状態のものがこちら↓です。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="JgGGWE" data-user="125naroom" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/125naroom/pen/JgGGWE">
  アコーディオン、シンプル版</a> by 125naroom (<a href="https://codepen.io/125naroom">@125naroom</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

Codepen↑の、この↓部分をクリックすると、大きな画面で表示されます。**この後の説明に従って、実際にCodepenの画面でコードをいじってみてください。**
![](https://i.gyazo.com/6684ec08a4420f3a2d605c3a656d1ef0.png)

大きな画面で開いたら、実際に見出しをクリックして開閉してみましょう。

![](https://i.gyazo.com/26606284dbf3bb4615b4f653bfc7a4b0.gif)

なお、ソースコードの行数は以下のようになっています。
- HTML：31行
- CSS：171行
- JavaScript：10行

「どこに着目して理解を深めたいか決める」ために、**このサンプルはどのような機能の集まりでできているか**をじっくり観察します。例えば、以下のような点はすぐに分かるでしょう。

- 見出しをクリックすると「中身です」が表示される。
- 再度見出しをクリックすると「中身です」が消える。

「アコーディオン」として最低限の機能ですね。もう少し詳しく、実装に近い観点でみていきましょう。

- 見出しをクリックすると、対応する「中身です」が表示される。**対応しない「中身です」は変化しない**。
- **「中身です」をクリックしても閉じない**。
- 「パッ」と表示/非表示になるのではなく、**「滑らかに」開閉する**。
- 開閉の際、他の見出しが**下に押し下げられる**。

「それって当たり前...」と思ったでしょうか。しかし自分でJavaScriptを書いてみると、なぜか上記のような細かい点がうまく行かないことも多いものです。この記事の最後にNG集を載せていますので、よくソースコードを見比べて、なぜうまく行かないのかも観察してみると良いでしょう。

さらに、アコーディオンが「開閉する」ことには直接関係ない、飾りのような部分も含めて、以下のような点も意識しておくと良いです。これは次のステップで、「関係ない部分を削る」ために必要な作業です。

- 見出しにマウスを当てるとマウスカーソルが手の形になる。
- 閉じている見出しには「＋」、開いている見出しには「ー」が表示されている。
- 開閉の際、「＋」「ー」が回転している。
- 見出しがそれぞれ別の色になっている。
- 見出しにマウスを乗せると見出しの色が少し白っぽくなる。離すと元に色に戻る。

![](https://i.gyazo.com/56e4649efe90be553c4bb8b3883cb9c7.png)

ここまで分解できたら、どこに着目するか決めましょう。「アコーディオン」なので、「開閉」の理解を深めたい、飾りの部分(「＋」「ー」ボタンの部分など)は今回は置いておこう...といったことですね。

# 関係ない部分を削る

さて、今回はアコーディオンの「開閉」に関するところに焦点を当てたいと思いますので、関係ない部分を削っていきます。JavaScript/jQueryに関する記事ですが、ここでは**CSSもガンガン削っていきます**。

デベロッパーツールを使いますので、開き方や要素の調べ方については、こちら↓の記事の`デベロッパーツールを開く`〜`デバイス表示`あたりまでをご覧ください。

https://qiita.com/yymmt/items/c3a015fa97d167ca0e6c#%E3%83%87%E3%83%99%E3%83%AD%E3%83%83%E3%83%91%E3%83%BC%E3%83%84%E3%83%BC%E3%83%AB%E3%82%92%E9%96%8B%E3%81%8F

### アコーディオンの外のリンク

この部分`(1,2)`はサンプルサイトへのリンクなので、「class="_a"」「.a」`(3)`に関連するところを削ります。また、ご丁寧にも「以下は不要です。」`(4)`とのことなので、これも削ってみましょう。
![](https://i.gyazo.com/b0194702cac7919949a16221983008eb.png)

### 見出しごとの色をなくす

まず「見出しの色は`background`だろう」と見当をつけます。デベロッパーツールで見出しを選択し、フィルタで`background`と入力すると、`.s_01 .accordion_one .accordion_header`で`background-color: #db0f2f;`を設定していることが分かります。
![](https://i.gyazo.com/38819fc17ac4f2c26e5f2ce92bdc50c5.gif)

cssから`background-color: #db0f2f;`を検索して削除します。この時、`color: #fff;`も合わせて消します。消さないと白地に白文字になって見えなくなってしまうためです。なお、Codepenでは自動的にプレビューが更新されます。
![](https://i.gyazo.com/dbf07df3f6b4206664fc12567c32673f.gif)

同様に、残りの背景色`(1,2)`も消していきます。空`{}`になった部分は消して良いです。
![](https://i.gyazo.com/6c276234bc4bfc7393395bfb7c82f982.png)

### マウスが乗った時の色の変化をなくす
マウスが乗った時の記述はcssの`hover`だろうと見当をつけます。`hover`のついた部分を消していきます。
![](https://i.gyazo.com/c87606fda9dd4504ee6bbd929787f6d1.png)

### 右の「＋」「ー」アイコンをなくす
デベロッパーツールで`(1)`部分を確認すると、`(2)`部分であることが分かります。HTMLの`(3)`該当部分を消していきます。3箇所あります。
![](https://i.gyazo.com/50773954cc4c5e410e0b75d0f2e6309c.jpg)

cssでは`.i_box`と付くところを削除します。
![](https://i.gyazo.com/28be7f36baecf3812776d85320cf940a.png)

### その他見栄えに関する部分をなくす
`width`, `height`, `margin`, `padding`, `font-size`, `font-weight`, `border` `(1)`などは見栄え上のことで、開閉には関係ないだろうと見当をつけ、消していきます。`display`, `position`, `z-index` `(2)`あたりはいったん残しておきます。
![](https://i.gyazo.com/e7f6fadb2d6fdf05b3413f904332a4ee.png)

この段階でcssはこれだけになります。
![](https://i.gyazo.com/aacdcac521cecce06747e0f2b02ee121.png)

ちゃんとアコーディオンとして開閉する状態を保っています。
![](https://i.gyazo.com/e3e893e37d5f63828686cb96e326e721.gif)

いったん、この状態のCodepenを置いておきます↓。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="jOYqjXq" data-user="yymmt" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/yymmt/pen/jOYqjXq">
  アコーディオン - 削る1</a> by yymmt (<a href="https://codepen.io/yymmt">@yymmt</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

### cssを削ったことで関係なくなったJavaScript部分をなくす
こちら↓では`toggleClass`で`open`クラスを付けたり外したりしていますが、すでに`open`クラスはHTMLにもCSSにもありませんので、JavaScriptからも消してしまいましょう。
![](https://i.gyazo.com/b7df6de01f39305768ee2714dd327261.png)

### 古い記述をなくす
`$(function(){`と`});`は、JavaScriptを`<head>`に書くことが慣習だった時代の名残りと思って良いでしょう。最近ではJavaScriptは`<body>`の末尾に書くことが多く、その場合はこの記述は不要です。
![](https://i.gyazo.com/bf8af4f90d24432cb88418b9766280cf.png)

ついでにコメントも消して、こう↓なりました。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="BaJzNvP" data-user="yymmt" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/yymmt/pen/BaJzNvP">
  Untitled</a> by yymmt (<a href="https://codepen.io/yymmt">@yymmt</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

アコーディオンとして開閉する状態を保っています。
![](https://i.gyazo.com/e3e893e37d5f63828686cb96e326e721.gif)

### 判断に困ったところは１行ずつ消して動作を確認する
`position: relative;` `(1)` は、「相対的な位置」に関する記述、
`z-index: +1;` `(2)` は、「表示の前後」に関する記述、
`transition-duration: 0.2s;` `(3)` は、「滑らかにCSSを変化させる」記述です。いずれもアコーディオンに関係しそうな感じはありますが、消してみると変わらず開閉しました。
![](https://i.gyazo.com/9b053196d91a858325508a9a9e60af09.png)

`display: none;` は、「非表示」にしておくための記述です。消してみると、「中身です」が最初から表示されてしまいました。これは残しておきましょう。
![](https://i.gyazo.com/5df1173e5f944ad6f96418712a2bd707.png)

HTMLの中で、CSSとJavaScriptに出てくるクラス名を確認します(青線部分)。出てこないクラス名は消してよいです。また、今回のCSSとJavaScriptではタグ名による選択がないので、クラスがなくなったタグ(赤線部分)も消してよいです。
![](https://i.gyazo.com/1df4aa84175bb83e778489b73069d305.png)

### 冗長な記述をなくす
`.s_01 .accordion_one .accordion_inner`とは、
「`s_01`クラスを持つ要素の子孫要素の中で、
`accordion_one`クラスを持つ要素の子孫要素の中で、
`accordion_inner`クラスを持つ要素」のことです。
単に`.accordion_inner`とだけ書いても同じですね。
![](https://i.gyazo.com/194a321fc44fc5db014015f6ae60a293.png)

JavaScriptの`.s_01 .accordion_one .accordion_header`も同様に、`.accordion_header`にします。

だいぶ減りましたね。

![](https://i.gyazo.com/4fb8b718404e80089d65b263cc4407a7.png)

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="abEZLBe" data-user="yymmt" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/yymmt/pen/abEZLBe">
  アコーディオン - 削る3</a> by yymmt (<a href="https://codepen.io/yymmt">@yymmt</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

アコーディオンとして開閉する状態を保っています。
![](https://i.gyazo.com/c237ec1ed4d98fc063132decc0d061dc.gif)

### いったんここまでのまとめ
ここまでで、

- サンプルのどこに着目して理解を深めたいか決める
- 関係ない部分を削る

を行いました。その結果、ソースコードの行数は、
- HTML：14行
- CSS：3行
- JavaScript：3行

と、かなり減りました。**「読める気がする」感**がだいぶ増したのではないでしょうか。

# console.log()で処理の一部を取り出して確認する

JavaScriptで `console.log(●●●●)` と記述することで、デベロッパーツールに`●●●●`部分を出力することができます。サンプルプログラムの一部を出力することで、理解が深まります。

### 準備

再度、「見たいところ以外を削ったアコーディオン」を見てみましょう。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="abEZLBe" data-user="yymmt" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/yymmt/pen/abEZLBe">
  アコーディオン - 削る3</a> by yymmt (<a href="https://codepen.io/yymmt">@yymmt</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

`↑`の`↓` `Edit on Codepen` をクリックすると、大きな画面で表示されます。
![](https://i.gyazo.com/6684ec08a4420f3a2d605c3a656d1ef0.png)

また、プログラムのボリューム的に、この`↓`レイアウトの方が見やすいかもしれません。
![](https://i.gyazo.com/dff69e9bedf7a67f3655f71abf365a08.png)

Codepenでデベロッパーツールを開くとこのようになります。今回は「コンソール」`(1)`を開いておきましょう。いろいろと赤文字`(2)`が表示されますが、Codepen側の都合で何か出力しているものと思われますので、「コンソールを消去」`(3)`で消しておきましょう。
![](https://i.gyazo.com/abac453a5365cc9cc7329e93e171c63f.jpg)

### $('.accordion_header')を出力してみる

「`$('.accordion_header')`は、`accordion_header`クラスを持つ要素を選択するjQueryの関数である」、ということは知ってはいても、「出力して」「目視した」ことはあるでしょうか。

Codepenの画面で、JavaScriptの1行目に、`console.log($('.accordion_header'));` `(1)`と入力し、そのまま数秒待ってみましょう。**ゆっくり打っていると、打ちかけの状態で実行されてしまいエラー表示になることがありますが、落ち着いて再度「コンソールを消去」して、続きを打ちましょう。**　コンソールに何やら`(2)`表示されます。▼`(3)`をクリックすると、詳細が表示されます。
![](https://i.gyazo.com/14fc15567fa546e28aa8e0e63c3379d7.png)

`0: div.accordion_header`部分にマウスを当てると、見出しがハイライトします。`$('.accordion_header')`が「見出し」を選択できていることを確認したことになります。
![](https://i.gyazo.com/74a6bce289f60f9fa9eecdc844ca2322.gif)

### $(this)を出力してみる

`$(this)`も見てみましょう。
![](https://i.gyazo.com/93f1438d7f6ac6b2ec46fe25013124b8.gif)

`console.log($(this));`を追記して、見出しをクリックしたところです。クリックした見出しだけが選択できていることを確認することができます。

`console.log($(this));`を追記するのは、元から記述されていた、
`$(this).next('.accordion_inner').slideToggle();`の直前が良いです。
変数は中身がどんどん変わったり、スコープと言って、変数の使える範囲が決まっていたりします。
`this`を確認したければ`this`の直前で`console.log`するのが良いです。

(なお、そもそも`this`は文脈によって意味が変わってしまうので、自分で書くときは`e.target`などの方が良いです。)

### nextを出力してみる
`$(this).next('.accordion_inner')`も見てみましょう。
先ほどの`$(this)`も残しておきたいので、先頭に`"1:",` `"2:",` などつけておくと見やすいです。
![](https://i.gyazo.com/78258ff0fde21aa0a9c5c828d4ce3a50.png)

`$(this)`が、クリックした見出し、
`$(this).next('.accordion_inner')`が、クリックした見出しに対応した「中身です」を選択していることを確認することができます。**実際に以下の動画のように操作してみましょう。**
![](https://i.gyazo.com/e181b743326efda8b4afe7879836551c.gif)

### いったんここまでのまとめ
`console.log()`で処理の一部を取り出して確認することで、実際にjQueryがどの要素を選択しているかを視覚的に確認することができました。これにより、

```javascript
$('.accordion_header').click(function(){
  $(this).next('.accordion_inner').slideToggle();
});
```

というプログラムが、

```
【見出し】 .click(function(){
  【クリックした見出し】 に 【対応する「中身」の要素】 .slideToggle();
});
```

と、意味を伴って読めると思います。ピリオド`.`は適宜`てにをは`にして読みましょう。残りの`.click`や`function()`や`.slideToggle()`は、元の意味を知らなくても、

```
【見出し】 を 【クリックした時に以下を実行する】
  【クリックした見出し】 に 【対応する「中身」の要素】 を 【開閉する】
```

と推測できるでしょう。推測できずとも、`jQuery slideToggle`などで検索すれば分かりそうです。少なくとも、`セレクタ`、`click`、`function`、`this`、`next`、`slideToggle`を全部調べるよりは、かなりハードルが下がったと思います。

# 「書ける」ようになるために
ここまで、サンプルの**読み解き**を解説してきましたが、**書ける**ようになるためのポイントも少し書いておきます。

### サンプルを複数探す
今回は`slideToggle`で開閉するサンプルでしたが、`slideUp`、`slideDown`で開閉したり、「すでに開いているかどうか」を判定するために`visible`を使うなど、様々なパターンがあります。今作ろうとしているものに近いものを探しましょう。

### 削ったものをコピペ
今回の要領で削ったものを、自分のサイトにコピペしてみましょう。動けばそれでよし。ちょっと見た目を変えたい、という場合も、「削ってない元のサンプル」に手を入れるよりはだいぶやりやすいと思います。

### 動かない場合
`console.log`で１つ１つの動作を確認してみましょう。例えば
`$('.accordion_header')` `(1)` を
`$('.accordion-header')` `(2)` と間違えている場合、`console.log($('.accordion-header'))`を追記しても要素が出力されず、`length: 0`とだけ出力されます。
![](https://i.gyazo.com/e4aeef141a29abf37319527d6bdce4e9.png)
![](https://i.gyazo.com/62ea496e6558930cf70fab987e983db4.png)

これにより、`$('.accordion-header')`のどこかに間違いがあることがわかります。(今回はハイフン`-`とアンダーバー`_`を間違えています。)１つ１つ修正していきましょう。

### 動くけどちょっと違う場合
次のNG集を見てみましょう。わずかな記述の違いで、いろいろな挙動が観察できます。**どの記述がどう影響するか**を把握しておくと、自分で作ったものが「ちょっと違う」原因も見つけやすくなります。

# NG集
冒頭で「アコーディオン」の分析をしたとき、「アコーディオンなんだから当たり前」に見える機能もしっかり観察することをお勧めしました。ここでは、わずかな記述の違いで、いろいろな挙動に変わる(変わってしまう)様子を見ていただければと思います。それぞれ、何が原因か観察してみましょう。(必要であれば`console.log()`などを追記してみましょう。**自分で作ったCodepenでなければ修正しても保存されませんので、どんどん修正してみてください。**)

- 見出しをクリックすると、対応する「中身です」が表示される。**対応しない「中身です」は変化しない**。

以下のように実装すると全ての「中身です」が開閉してしまいます。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="popbdGb" data-user="yymmt" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/yymmt/pen/popbdGb">
  アコーディオン - NG1</a> by yymmt (<a href="https://codepen.io/yymmt">@yymmt</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- **「中身です」をクリックしても閉じない**。

以下のように実装すると「中身です」をクリックした時にも閉じてしまいます。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="gOoMXyJ" data-user="yymmt" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/yymmt/pen/gOoMXyJ">
  アコーディオン - NG2</a> by yymmt (<a href="https://codepen.io/yymmt">@yymmt</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- 「パッ」と表示/非表示になるのではなく、**「滑らかに」開閉する**。

以下のように実装すると「パッ」と表示/非表示になります。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="PoEzOvr" data-user="yymmt" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/yymmt/pen/PoEzOvr">
  アコーディオン - NG3</a> by yymmt (<a href="https://codepen.io/yymmt">@yymmt</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- 開閉の際、他の見出しが**下に押し下げられる**。

以下のように実装すると見出しが押し下げられません。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="gOoMXNJ" data-user="yymmt" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/yymmt/pen/gOoMXNJ">
  アコーディオン - NG4</a> by yymmt (<a href="https://codepen.io/yymmt">@yymmt</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>