[Javascript]  Javascript Pattern要約 - オブジェクト生成パターン

## ネームスペース·パターン

ネームスペース·パターン

・容易に実装できるパターンであり、全域変数の個数を減らし、変数名が不要に長くなることを防止する。
・全域ネームスペースオブジェクトはよく大文字で宣言する。

``` javascript
// アンチパターン
function Parent() {
}
function Child() {
}
var some_var = 1;
var module1 = {};
var module2 = {};

// 改善案
var MYAPP = {};
MYAPP.Parent = function() {

};
MYAPP.Child = function() {

};
MYAPP.some_var = 1;

MYAPP.modules = {};
MYAPP.modules.module1.data = {a:1, b:2};
MYAPP.modules.module2 = {};
```
・このパターンの短所は次のようである。
１. すべての変数と関数に接頭語をつけるため、全体コード量が長くなりダウンロードファイルのサイズが増加。
２. 全域インスタンスが1つなので、部分が修正されると他の全域インスタンスも全て修正される。
３. 名前が長くなるので、プロパティ判別のための検索作業が長くかかる。 （サンドボックスパターンで解決）

汎用ネームスペース関数
・プログラムサイズが大きくなって複雑になると、ネームスペース使用において次のような点検が必要である。

``` javascript
var MYAPP = {};
// 1. 基本
if (typeof MYAPP === "undefined") {
  var MYAPP = {};
}
// 2. *おすすめ*
var MYAPP = MYAPP || {};
```
・上記コードをオブジェクト生成ごとに追加するよりは下記のように関数で別途生成する方が効果的である。

``` javascript
var MYAPP = MYAPP || {};

MYAPP.namespace = function(ns_string) {
  var parts  = ns_string.split('.'),
      parent = MYAPP,
      i;

  if (parts[0] === "MYAPP") {
    parts = parts.slice(1);
  }

  for (i = 0; i < parts.length; i += 1) {
    if (typeof parent[parts[i]] === "undefined") {
      parent[parts[i]] = {};
    }

    parent = parent[parts[i]];
  }

  return parent;
}
```
・上コードは下記の様に、使用できる。

``` javascript
MYAPP.namespace("MYAPP.modules.module2");
// 上コードは下記と同じ
var MYAPP = {
  module : {
    module2 : {}
  }
};

var module2 = MYAPP.namespace("MYAPP.modules.module2");
module2 === MYAPP.modules.module2; // true
```

## 依存関係宣言

・関数やモジュール内の最上段に依存関係があるモジュールを宣言するのがよい。

``` javascript
var myFunction = function () {
  var event = YAHOO.util.Event,
      dom   = YAHOO.util.Dom;
};
```
・上記のパターンの長所は次の通りである。

``` javascript
var myFunction = function () {
  var event = YAHOO.util.Event,
      dom   = YAHOO.util.Dom;
};
```
1. 依存関係が明示的なため、ページ内に必ず盛り込むべきスクリプトファイルが分かりやすい。
2. 変数の値探索は、yahoo.util.dom のような重なりプロパティよりもはるかに速い。
3. 高級Compressor は全域変数名変更は危険であるため縮約せず、上記イベントのような地域変数はa に縮約する。

コード圧縮例

``` javascript
// 1.
function test1() {
  alert(MYAPP.modules.m1);
  alert(MYAPP.modules.m1);
}
// 上コード圧縮
// alert(MYAPP.modules.m1);alert(MYAPP.modules.m2);

// 2.
function test2() {
  var modules = MYAPP.modules;
  alert(modules.m1);
  alert(modules.m2);
}
// 上コード圧縮
// var a=MYAPP.modules;alert(a.m1);alert(a.m2);
```

## 非公開のプロパティとメソッド

クローザーを用いた非公開メンバは以下のように実装する。

``` javascript
function Gadget() {
    var name = "iPhone";
    this.getName = function() {
      return name;
    };
}
var toy = new Gadget();
console.log(toy.name); // undefined
console.log(toy.getName()); // "iPhone"

var myobj;
(function () {
  var name = "Android";

  myobj = {
    getName: function() {
      return name;
    }
  };
}());

myobj.getName(); // "Android"

var myobj = (function () {
  var name = "Android";
  return {
    getName: function() {
      return name;
    }
  };
}());

myobj.getName(); // "Android"
```
・非公開メンバの実装方法:関数内で地域変数と宣言したプロパティを関数で囲む。
・生成者を利用して非公開メンバーを作る場合には、生成者で新しいオブジェクトを作るごとに非公開メンバーが再生成される短所がある。
・上記のような短所はプロトタイプで補完が可能である。

``` javascript
function Gadget() {
  var name = "Android";
  this.getName = function () {
    return name;
  };
}

Gadget.prototype = (function () {
  var browser = "Mobile";
  return {
    getBrowser : function() {
      return browser;
    }
  };
}());

var toy = new Gadget();
console.log(toy.getName()); 
console.log(toy.getBrowser()); 
```

## モジュールパターン

モジュールパターン

・モジュールパターンを利用すれば個別のコードを緩く結合することが可能だ。
・大量のコードを構造化し整理するのに役立つ。

モジュールパターン適用のための手順

``` javascript
MYAPP.namespace("MYAPP.utilities.array");

MYAPP.utilities.array = (function () {
  return {
    inArray: function (needle, haystack) {
      // ...
    },
    isArray: function (e) {
      // ...
    }
  };
}());

MYAPP.utilities.array = (function () {

  var uobj  = MYAPP.utilities.object,
      ulang = MYAPP.utilities.lang,

      array_string = "[object Array]",
      ops = Object.prototype.toString;

  
  return {
    inArray: function (needle, haystack) {
      // ...
    },
    isArray: function (a) {
      return ops.call(a) === array_string;
    }
  };
}());

MYAPP.utilities.array = (function () {

  var uobj  = MYAPP.utilities.object,
      ulang = MYAPP.utilities.lang,

      array_string = "[object Array]",
      ops = Object.prototype.toString,

      inArray = function (needle, haystack) {
        // ...
      },
      isArray = function (a) {
        return ops.call(a) === array_string;
      };

  return {
    isArray : isArray
  };
}());
```

## サンドボックス·パターン

サンドボックスパターンはモジュール間の相互に影響を及ぼさずに動作できる環境を提供する。