「JavaScriptパターン」ピックアップ

## はじめに
久々にjavascriptを弄ることになり、おさらいで各種書籍を読み直しています。
この際自分の中での暗黙知を明文化しておきたいと思い、しっくり来ているところだけピックアップしてみました。
（ほぼ自己メモです。）

### for-inループ
+ プロトタイプ連鎖からきたプロパティを除外するためhasOwnPropertyを使う

```js:pattern00.js

// for-inループ

var man = {
    hands: 2,
    legs: 2,
    heads: 1
};

for (var i in man) {
    if (man.hasOwnProperty(i)) {    // フィルタ
        console.log(i, ":", man[i]);
    }
}
```

### forループ
+ myarray.lengthに対してのキャッシュ(ループ毎に問い合わせるよりも相当速い)
+ 単独varパターン(var宣言は１つに、そして関数先頭で)
+ for末尾のカウンタインクリメントにi++は使わず、i += 1にする。(++,--の「過剰なトリック」を避けるため)

```js:pattern01.js
function looper() {
    var i = 0,
          max,
          myarray = [];
    // ...
    
    for (i=0, max = myarray.length; i < max; i += 1){
        // myarray[i]に対する処理
    }
}
```


### switch
+ switchとcaseを揃える(波括弧のインデントルールの例外)
+ case内のコードはインデントする
+ caseの最後はbreak; で終わらせる
+ 意図的にbreakを省略して次のcaseに続けるのは避ける
+ switchの最後はdefault: で終わらせる

```js:pattern02.js

var inspect_me = 0,
    result = '';
    
switch (inspect_me) {
case 0:
    result = "zero";
    break;
case 1:
    result = "one;"
    break;
default:
    result = "unknown";
}
```

### インデント
+ 空白4個に揃える(JSLintのデフォルトなので)
+ インデントが空白かタブか、インデント幅は？等の話題は宗教戦争。正解は無い。(が必ず統一すること)
+ ifやforの中に文が１つしかなくても、波括弧は省略しない(文１カッコ無しだと、後々うっかり追加でインデント狂う副作用があるため)

```js:pattern03.js
function outer(a, b) {
    var c = 1, 
        d = 2, 
        inner;

    if (a > b) {
        inner = function() {
            return {
                r : c - d
            };
        };
    } else {
        inner = function() {
            return {
                r : c + d
            };
        };
    }
}
```

### 命名規則
+ コンストラクタの頭文字は大文字
` var adam = new Person();` 
` function MyConstructor() {...}` 

+ 関数名はキャメルケース
` myFunction()` 

+ 変数名は小文字アンダースコア区切り(関数名と見分ける事ができるため)
` var favorite_bands = "hoge";` 

+ 定数は大文字、単語区切りはアンダースコア
` var MAX_WIDTH = 800;`

### コメント
+ 習慣にするのが難しいけれど最も重要なのは、コメントを最新に保つこと
(古くなったコメントは誤解を生み、コメントが無い方がよっぽどましな場合もある)
+ 以下はJSDocの例

```js:pattern04.js
// JSDoc記法

    /**
     * 文字列を反転させる
     *
     * @param  {String} 反転させたい文字列
     * @return {String} 反転された文字列
     */
    var reverse = function(input) {
        // ...
        return output;
    }
```

+ YUIDocのデモは[こちら](http://jspatterns.com/book/2/)
以下にも転記

```js:pattern05.js
    /**
     * My JavaScript application
     *
     * @module myapp
     */
    var MYAPP = {};
    /**
     * A math utility
     * @namespace MYAPP
     * @class math_stuff
     */
    MYAPP.math_stuff = {

        /**
         * Sums two numbers
         *
         * @method sum
         * @param  {Number} a First number
         * @param  {Number} b The second number
         * @return {Number} The sum of the two inputs
         */
        sum : function(a, b) {
            return a + b;
        },

        /**
         * Multiplies two numbers
         *
         * @method multi
         * @param  {Number} a First number
         * @param  {Number} b The second number
         * @return {Number} The two inputs multiplied
         */
        multi : function(a, b) {
            return a * b;
        }
    };

    /**
     * Constructs Person objects
     * @class Person
     * @constructor
     * @namespace MYAPP
     * @param {String} first First name
     * @param {String} last Last name
     */
    MYAPP.Person = function(first, last) {
        /**
         * Name of the person
         * @property first_name
         * @type String
         */
        this.first_name = first;
        /**
         * Last (family) name of the person
         * @property last_name
         * @type String
         */
        this.last_name = last;

    };

    /**
     * Returns the name of the person object
     *
     * @method getName
     * @return {String} The name of the person
     */
    MYAPP.Person.prototype.getName = function() {
        return this.first_name + ' ' + this.last_name;
    }; 
```

### コンストラクタ
+ コンストラクタは単なる関数ですが、newを使って呼び出すことができる。
+ newを付け忘れて呼ぶと構文エラーにも実行時エラーにもならないが、thisがグローバルオブジェクトを指してしまう。

#### コンストラクタ関数を*new*を使って呼び出す時、関数内部では以下のようになります
+ 空のオブジェクトが作成され、変数thisで参照される。thisはこの関数のプロトタイプを継承する。
+ thisが参照するオブジェクトにプロパティとメソッドが追加される。
+ thisが参照する新しく作られたオブジェクトは、関数の最後で暗黙に返される。

```js:pattern06.js
var Person = function(name) {
    this.name = name;
    this.say = function() {
        return "I am " + this.name;
    };
};
```

####上記例ではthisにメソッド say()を追加しているが、メモリが無駄なのでプロトタイプに追加すべき

```js:pattern07.js
Person.prototype.say = function () {
    return "I am " + this.name;
};
```