「JavaScript初級者のためのコーディングガイド」に補足を試みる

## はじめに

http://qiita.com/raccy/items/bf590d3c10c3f1a2846b を見ていたら、はてブに「理由がないから」ということがよく挙がっていたので、理由をつけてあげたら有益な内容になるかな？と思い、拙いながらも補足を試みようと思います。

`【2017 1/3 15:10 追記】`
元記事の前提は`gulp`などを使って`minify`なども行なえる（もしくは行う目標がある）前提の様子なので、中級者以上がターゲットかなーと思いました。そのつもりで読むととてもいい記事だと思っています。

「最新のJSの書き方を覚えてあとは変換機能に任せればレガシーなJSのキツイところに向き合わなくて済みますよ？」みたいなイメージだとわかりやすいかな？

## :no_entry_sign: ==、!=

#### 理由
暗黙の型変換が発生して、別の型の比較が真で扱われてしまう場合があるため。

#### 解説
サンプルコードにも出ていますが言葉足らずな気がするので

-  `==` では文字列の`"1"`と、数値の`1`が一致すると判断されてしまう
-  `===` では文字列の`"1"`と、数値の`1`が一致すると判断されない

ということになります。そして「型が違うのに一致する」というのは何かプログラムが間違ってる可能性が高いので、禁止する方が良いということだと思います。

#### 参考
http://stackoverflow.com/questions/359494/which-equals-operator-vs-should-be-used-in-javascript-comparisons 
英語ですがわかりやすい一覧を出したりして丁寧な解説があります。Great！

## :no_entry_sign: var

#### 理由
`let`、`const`の方がスコープを狭くすることができて、変数が再代入されるかどうかを明瞭に示せるから。

#### 解説
まず、`var`は古くからある書き方です。最新のJSで`let`、`const`が追加されました。大きな違いが下記です。下に行くほど厳格になります。

- `var` : スコープの単位が`function`、再代入可能
- `let` : スコープの単位が`{}`、再代入可能
- `const` : スコープの単位が`{}`、再代入不可能

そして、最新のJSではなるべく厳格な書き方から使う方が良いとされているので、「まず `const` を検討し、そうでなければ `let` を検討する」（と、ほとんど`var`は必要なくなる）。という感じかと思います。

#### 参考
http://qiita.com/niisan-tokyo/items/bacb5ed98ea10831eeba
コード付きで解説されています。多謝！

## :no_entry_sign: 関数宣言、関数式、ジェネレーター宣言
話が複雑になりそうなので一旦飛ばします。時間がある時に書くかも。
私は関数宣言しても別に良いと思っている派です。


## :no_entry_sign: コールバックに関数式
これはケースバイケースになると思います。`function`と`=>` は`this`の束縛方法が違うので、用途に応じて分ける方が良いのではないでしょうか。可読性のためになるべく`=>`を検討して、難しい場合には`function`くらいでも良いような気がします。

特に、jQueryのコールバックでは`function`にしておいた方が良いこともあるかもしれません（`jQuery`はコールバックは`function`が渡される前提で用意されている部分が多いと思います）。

#### 参考
http://analogic.jp/arrow-function/#caution
`function`と`=>`の動作の違いについて丁寧に解説されています。

`this`について知りたい場合には下記も良いかもしれません。
http://qiita.com/takeharu/items/9935ce476a17d6258e27

## :no_entry_sign: for文
#### 理由
~~より抽象度の高い関数が最新のJSでは提供されているため（？）~~

#### 解説
~~集合（配列や`Object`）の中身を順番に取り出すという`forEach`が提供されているので、それを使いましょう、という感じ（で、合ってます？）。~~

~~`for(;;)`はともかく、`for...in`や`for...of`も禁止する理由が私にはよくわかりませんでした。~~

#### `【2017/1/4 21:30 追記】`
http://qiita.com/raccy/items/bf590d3c10c3f1a2846b/revisions/10
元記事は最初は「`forEach`推し」でしたが今は宗旨替えをされている様子です。

#### 提案
反復についてちょっと構成を変えて記述したいと思います。言っている内容はそれほど変わりません。下記のような優先度で考えると良いのでは無いでしょうか。様々な意見を持つ方がいることは周囲の議論からもわかると思いますので、あくまで一つの提案です。

##### 配列について

| 優先度 | 反復の方法 | 理由・備考 |
|:-----------|------------|:---------------|
| 1       | map, reduce など | 反復以上の意味を持ち抽象度が高いため、使えるなら使いたい |
| 2     |   for...of | 配列によらず使える汎用性があるため |
| 3     |   forEach  | 少なくともインデクス操作をせずに済むため |
| 4     |   for(;;)  | どうしても困ったらこれ | 

##### Object（連想配列）について


| 優先度 | 反復の方法 | 理由・備考 
|:-----------|:------------|:------------|
| 1       | Object.entries | まだ対応している処理系が少ないが、for...ofと組み合わせるとクール |
| 2 | Object.keys | 配列として取れるので、あとは配列として扱う | 
| 3     |   for...in  | プロトタイプチェーンを操作している際に`hasOwnProperty`と組み合わせないと危険な場合がある |

##### 優先度について
もちろん上から順に適応を考えるのが良いのですが

- 各種環境に変換させるから強気で選択しても大丈夫と考える
- ある程度ブラウザがネイティブでサポートしている機能を優先する
- 古いブラウザに対応しなければならないので出来るだけレガシー

などで取捨選択する必要があります。これは参加されているプロジェクトのポリシーや成果物を提供する先によっても違うでしょう。

#### 参考
簡単なサンプルを[Babelでやりました](http://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=es2015&experimental=false&loose=false&spec=false&code=%2F%2F%20%E9%85%8D%E5%88%97%E3%81%A7%E3%81%AE%20for...of%0Afor%20(let%20a%20of%20%5B1%2C2%2C3%5D)%20%7B%0A%20%20console.log(a)%3B%0A%7D%0A%0A%2F%2F%20%E7%8B%AC%E8%87%AA%E3%81%AB%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F%E3%82%A4%E3%83%86%E3%83%AC%E3%83%BC%E3%82%BF%E3%81%A7%E3%81%AE%20for...of%0Aconst%20o%20%3D%20%7B%7D%3B%0Ao%5BSymbol.iterator%5D%20%3D%20function()%7B%0A%20%20let%20i%20%3D%200%3B%0A%20%20return%20%7B%0A%20%20%20%20next%3A%20function()%7B%0A%20%20%20%20%20%20return%20%7Bvalue%3A%20i%2B%2B%2C%20done%3A%203%20%3C%20i%7D%3B%0A%20%20%20%20%7D%0A%20%20%7D%3B%0A%7D%3B%0A%0Afor(let%20b%20of%20o)%20%7B%0A%20%20console.log(b)%3B%0A%7D%0A%0A%2F%2F%20Object.entries%20...%E3%81%AF%E3%80%81%E5%A4%89%E6%8F%9B%E3%81%95%E3%82%8C%E3%81%BE%E3%81%9B%E3%82%93%E3%81%A7%E3%81%97%E3%81%9F%E3%80%82%E5%87%A6%E7%90%86%E7%B3%BB%E3%81%AE%E9%80%B2%E5%8C%96%E3%82%92%E5%BE%85%E3%81%9F%E3%81%AA%E3%81%84%E3%81%A8%E3%81%84%E3%81%91%E3%81%AA%E3%81%84%E3%81%A7%E3%81%99%E3%81%AD%0Aconst%20obj%20%3D%20%7Ba%3A%20111%2C%20b%3A%20222%2C%20c%3A%20333%7D%0Afor(const%20%5Bkey%2C%20value%5D%20of%20Object.entries(obj))%20%7B%0A%20%20console.log(%60%24%7Bkey%7D%3A%20%24%7Bvalue%7D%60)%0A%7D%0A&playground=true)


## :no_entry_sign: プロトタイプ作成に関数定義

#### 理由
最新のJSではクラスベースの書き方が可能になっているので、クラスのようなものを作成したい場合にはその構文を用いる方が可読性が良いため。

#### 解説
レガシーな書き方はかなり冗長であったので、クラスが導入されました。背景色々ありそうなので、ここではシンプルな回答にとどめます。

## :no_entry_sign: undefined
#### 理由
`undefined`はグローバル変数であるため、どこかで代入されて別の値が入っている危険があるから。

#### 解説
参考に譲ります。とても丁寧です。でも、これ代入しちゃうことあるのかなぁ...。

#### 参考
https://liginc.co.jp/web/js/38494
丁寧に書いてあります。素敵！

## :no_entry_sign: delete
#### 理由
ちょっと明瞭にわかりませんでした。可読性のためなのでしょうか。

#### 解説
どちらかと言うと「オブジェクトから要素を削除する」目的で利用されると思うので、間違えないために、なのかもしれません。ごめんなさい、よくわかりませんでした。

#### 参考
http://alphasis.info/2013/01/javascript-operators-delete/
よく見る使い方はこちらで解説されています。ありがとう！

#### `【2017 1/3 15:10 追記】`
確かに `delete`した際の配列の挙動には要注意ですね。
https://syncer.jp/javascript-reverse-reference/array-remove
のように、 `splice` を使うと良いでしょう。わかりやすい記事で素晴らしい！

## :no_entry_sign: 厳格モードで削除される機能
※ 厳密モードより厳格モードの気がするので、そう書きます。

#### 理由
厳格モード（`use strict`を利用するとなります）をなるべく守ることで、コードの間違いを減らすため。

#### 解説
厳格モードで書く方が品質の高いコードになるので、推奨されています。このモードを利用した際に幾つかの機能がエラー扱いされて使えなくなります。`with`はその一種です。悪名高い暗黙のグローバル変数も、このモードではチェックしてくれます。

どちらかと言うと、「なるべく厳格モード有効で書きましょう」みたいな感じと受け止めると理解しやすいと思います。

#### 参考
https://msdn.microsoft.com/ja-jp/library/br230269(v=vs.94).aspx

MDNよりもスッキリして見やすかったのでご紹介。


## :no_entry_sign: 暗黙のセミコロン;
#### 理由
予期しない構文の解釈をされてしまう可能性があるため。

#### 解説
`JavaScript`はセミコロンを一つの単位で区切るようになっていますが、多くの場所で省略しても動作します。処理系が予測してセミコロンを補ってくれるのですね。

ただ、これが予期しない区切りで扱われるケースがあったり、変換する際に誤変換するような場合があるので、あまり処理系に任せずに、自分で書きましょうという意味合いかと思います。

#### 参考

https://www.webprofessional.jp/why-use-javascript-style-guide/ 

`JavaScript Standard Style` の解説（Cool!）なのですが、こちらは暗黙のセミコロンを積極的に活用するルールになっています。色々と流派があるんだなぁと思っていただければ幸いです。

## :no_entry_sign: {の前での改行

こちらは一旦放置します。次の 「`return`のみの行」が言いたいことにも思えますので。


## :no_entry_sign: returnのみの行

#### 理由
想定と違う区切りを処理系が判断してしまい、誤動作の危険があるため。

#### 解説
元記事のサンプルコードにも出ていますが、セミコロンを処理系が勝手に補った結果、意味合いが変わってしまうということですね。

```js
return 
  x * i;
```

```js
return; # 処理系がセミコロンを補って解釈。ここでリターン
  x * i; # このコードは呼ばれない
```

## :no_entry_sign: 無名関数で囲む
~~ごめんなさい。私は無名関数で囲っていいと思っていました。勉強不足です...。これってツールを使って変換される前提の話なのでしょうか（ブラウザの開発でもCommonJSにのっとれ、みたいな？）。よく分かる人フォローくだされ。~~

#### `【2017/1/4 21:30 追記】`
http://qiita.com/ms2sato/items/94ed459640a1d89cb4de#comment-79b45b3e672f739e9004
フォローいただきまして、やはりこれは何がしかの変換前提で書かれていた様子です（と、言うより元エントリが「ES6で書けるようにBabelなどの変換をすること」を前提で書かれています）。変換の際に無名関数で囲んでくれるような仕組みを使えば、気にしなくて良いという解釈で良さそうですね。Thanks!

#### 参考
モジュールベースが気になる人は`Webpack`とか`Browserify`とか調べてみるといいかも？
そこまででなくとも、`CoffeeScript`などは変換時に無名関数で囲ってくれたりします。

## :no_entry_sign: UTF-8以外のエンコード
#### 理由
今は`UTF-8`がデファクトスタンダードなので、別のエンコードを選ぶ理由がないため。

## :no_entry_sign: ES5.1以前のJavaScript
#### 理由
記述するためのJavaScriptは最新のJSにして、過去の版への対応は変換ツールに任せる方が効果的なため。

#### 解説
2017年１月現在、一部の開発ではブラウザで動作する`JavaScript`を直接記述することが減ってきています。`トランスパイル`という言葉を知るとわかりますかね。
今だと`Babel`や`TypeScript`が多いのでしょうか。

これらで記述するとレガシーな`JavaScript`に変換できる仕組みがあるので、記述する際は最新のJSや別の言語で記述して、多くのブラウザで動くレガシーな`JavaScript`に変換できます。

## :no_entry_sign: IE対応

~~クライアントやユーザー等、他人に縛られない開発ができるならば（例えば学習のために`JavaScript`を学ぶなど）、それで良いでしょうね。というわけで解説はなしです。~~ 

#### `【2017 1/3 15:10 追記】`
http://qiita.com/raccy/items/bf590d3c10c3f1a2846b#comment-a9fb13a9f5b45403ecb1
によると少し意味合いが違いますね。

IE対応を無視するという意味ではなくて、トランスパイルされたコードがIE対応をしていると想定していて、単体でIEのためのコードを考える必要はないのではないか？という想定だと思われます。

※ ajaxのクロスブラウザ対応とかはjQueryなんかで良いのかな。DOM操作はするな、だけど他は禁止されていないのだし。

## :no_entry_sign: underscore
おそらく多くの機能が最新の`JavaScript`にも取り込まれているからかと思いますが、個人的には必要ならば使って良いと思いますので解説はなしです。

#### `【2017/1/4 21:30 追記】`
#### 参考
http://qiita.com/ossan-engineer/items/ad5313d84da82c6ac421
かなりの機能が標準に各種ブラウザで組み込まれていることが確認できます。Good!

## :no_entry_sign: jQueryによるDOM操作
やっていいと思いますので解説はなしです。


## おしまいに
とりあえず短時間でババッと書いただけなので、不足あったら編集リクエストとかくれると泣いて喜びます！誤りも指摘してくださったら嬉しいです！

私の見立てでは、元資料は下記くらいの人が見ると為になるような気がします。 ~~ただし、IEを捨てている書き方だったので、仕事でやっている人ではないと思います。残念ながらIE11対応はまだ要求されることが多いのではないでしょうか。~~ （意味合いが違ったので、IEの禁止について確認してください）

- 「初心者だけど、学ぶのは最新のJSで過去なんかショートカットしたい」「過去の互換性なんて気にしない」という最新を知りたくてウズウズしている人。そしてトランスパイルの環境を用意するなど、多少苦労があっても乗り越えられる人
- すでにレガシーなJavaScriptを書いているが、最新記法への脱皮を試みようとしていて、何が次のステップに必要なのか分かりかねている人
- すでに他の言語を学んでいるが、これから乗り換えるのに最新のJavaScriptのことがわかれば一旦良いと考えている人

#### `【2017/1/4 21:30 追記】`
元記事も参考にされていた`Airbnb`のスタイルガイドを日本語訳されていた方がいらっしゃるそうで、こちらも参考にされると勉強になりそうですよ！
http://mitsuruog.github.io/javascript-style-guide/#%E9%96%A2%E6%95%B0functions



## その後
#### `【2017 1/3 15:10 追記】`
http://qiita.com/raccy/items/bf590d3c10c3f1a2846b#comment-a9fb13a9f5b45403ecb1
を反映しました。 
該当箇所には `【2017 1/3 15:10 追記】` をつけています。

#### `【2017/1/4 21:30 追記】`
http://qiita.com/ms2sato/items/94ed459640a1d89cb4de#comment-79b45b3e672f739e9004
を反映しました（ @teradonburi さんに感謝 ）。 

コメントでの議論や
http://qiita.com/raccy/items/bf590d3c10c3f1a2846b/revisions/10
に追随しました。こちらもforについては大幅に加筆しています（ @kazatsuyu さんありがとうございました）。

該当箇所には `【2017 1/4 21:30 追記】` をつけています。