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

  • 422
    Like
  • 16
    Comment

はじめに

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

理由

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

解説

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

  • 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...infor...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でやりました

: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のみの行

理由

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

解説

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

return 
  x * i;
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年1月現在、一部の開発ではブラウザで動作するJavaScriptを直接記述することが減ってきています。トランスパイルという言葉を知るとわかりますかね。
今だとBabelTypeScriptが多いのでしょうか。

これらで記述するとレガシーな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 追記】 をつけています。