JS実装の基本
コード規約を守る
Javascriptはどのように書いても間違いではないため、人によっていろんな書き方があります。
そのため、コードを見るとき可読性が低くなってしまったり、バグを見つけづらくなってしまいます。
そういったことを避けるためにも コード規約は守ったほうがよい のです。
たぶん社内では以下のコード規約が主流だと思うので紹介しておきます。
少なくとも以下を守るだけでもだいぶ見やすくなります。
- 定数と変数の区別(HOGE_HOGE,hogehoge)
- クラス名はupperCamelCase、変数名,メソッド名はlowerCamelCase(Class,variable)
- インデントの調整
- 名前空間汚染の回避(Namespaceを作る)
定数と変数の区別(HOGE_HOGE,hogehoge)
定数は基本的に変更しない(上書きしない)値でいろんな箇所で使われるものです。
たとえば全画面で使うカラーマップなどを用意しておけば定数を呼び出すだけで決められた色に指定できますね。
var COLOR_MAP = {
BASE:'#e6e6e6',
POPUP_EDGE:'#333333',
};
また定数と変数をちゃんと区別することで、どこを修正すればよいか、この変数は書き換えてもいいのか、がよりわかりやすくなります。
クラス名はupperCamelCase、変数名、メソッド名はlowerCamelCase(Class,variable)
//クラス名
var Bird = function(){
this.initialize();
}
var p = Bird.prototype;
//メソッド名
p.initialize = function(){
//変数名
this.name = 'ひよこ';
};
p.hamming = function(){
alert('ピヨ');
};
見たまんまです。
インデントの調整
インデントの調整はインデント数の統一だけでなく、変数代入時にも統一しておくと見やすくなって個人的に好きです。
//普通に書く
var hoge1 = 'hoge1';
var hogehoge2 = 'hoge2';
var hogehogehoge3 = 'hoge3';
//こっちのほうが見やすい気がする
var hoge1 = 'hoge1';
var hogehoge2 = 'hoge2';
var hogehogehoge3 = 'hoge3';
名前空間汚染の回避(Namespaceを作る)
グローバル空間を汚染しはじめると、デバッグしづらかったり、他のライブラリやコンポーネントと結合しづらくなるので名前空間を作って回避した方がいいと思います。
var namespace = {};
namespace.Bird = function(){};
namespace自体はJSにはないのでJavaのような厳密な形式でなくても良いと思います(呼び出しが面倒だしね)
//ちなみにJava
var mScrollView = new com.sonicmoov.app.view.ScrollView();
//Javaはimportすればnamespace省略できるけどjsには当然そんな機能などない
補足
また上記のチェックにはgrunt-contrib-jshintをwatchと組み合わせて使えば自然とコード規約を守れるようになります。
加えて jQueryを使うとき にはjQueryオブジェクトとそうでないものを区別するためにjQueryオブジェクトの先頭に $ をつけると代入ミスが減るのでおすすめです。
var $container = $('#container');
コメントを書く
コメントは必ず書いたほうがいいです。
修正時にあのとき自分は何を思ってこのコードを書いたんだ…というのはよくある話しです。ではなにをどこに書いたらいいのか。
書いたほうがいいこと
- その時気づいたことや調べてわかったこと
function draw(){
/*
clearRectを使うよりも
canvas.width=canvas.widthを使うほうがパフォーマンスが良い
*/
this.canvas.width = this.canvas.width;
}
- なぜそうなっているかあとで読んでもわからなそうなとき
/**
* a bar width rate
* |////|
* |////|
* |////|
* --------------
* 25%|50% |25%
* 6px|12px|6px
*/
var barLeft = drawWidth * 0.25;
var barWidth = drawWidth * 0.5;
var barRight = barLeft + barWidth;
- 仕様
あるといいかも
/**
* @param {Array<Number>} list 数値を含む配列
* @return {Number} max 最大値
*/
function findMax(list){
var max = 0;
//なんか処理
return max;
}
書かなくてもいいこと
- あまりに明瞭なこと(メソッドの説明など)
/**
* 引数a1とa2を加算して返す
*/
function add(a1,a2){
return a1 + a2;
}
JSdocなどのドキュメント生成ツールを使う
ドキュメントを作りたい時はドキュメント生成ツールを使います。
JSDocの規約に沿えば、一定のクオリティのドキュメントが出来上がりますが、だからといって上記ようなコメントを書かなくてもよいということではありません。
オブジェクト指向
オブジェクト指向と書きましたが、いきなりではハードルが高すぎるのでJavascriptでコンポーネントを作る程度のお話です。ここでいうコンポーネントとは 特定の役割をもったオブジェクト という意味です。
なぜ特定の役割を持ったコンポーネントを作らないといけないのかというと、それはひとえに 可読性 と 再利用性 です。
たとえばjqueryの初期化関数内にすべての処理をばーっと書くと何をしているのかよくわからない上に、それを理解するのにも時間がかかります。それにもしかしたら他の案件でも特定の機能だけを使い回したいといった場合に簡単に使いまわせたら便利ですよね。
そうならないためにも役割で実装を分けます。
この役割とは主に Model と View です。
Model
主にデータの管理に責任をもつオブジェクトです。
- 通信処理
- データの取得、パース、保存など
View
主に表示に関して責任を持つオブジェクトです。
- データをなんらかの形で出力する
- ユーザー操作を受け取る
Backbone.jsやAngular.jsなどのフレームワークを使ったことがある人はMVC(Model,View,Controller)やMVVM(Model,View,ViewManager)、MVW(Model,View,Whatever)などの言葉を聞いたことがあるかもしれません。どのフレームワークにも必ずModelとViewが入っていますね。それぐらい基本的な役割なのです。