最近の行儀のよい JavaScript の書き方

JavaScriptは移り変わりの早い言語です。
もう1年以上経っていますし、記事のメンテもちゃんとできていないので、消し線を入れることにしました。

参考程度のために記事は一応残しますが、より新しい情報を読まれることをお勧めいたします。

~~はじめに
---~~

~~最近では JavaScript の実行環境はブラウザに限りません。（node.js, Web Workers）
また、旧来のような `<script>` 経由でのロードもとうに古くなっています。今は CommonJS スタイルで、`require` を用いたモジュールのロードを行なうことがより良いとされています。~~

~~ですから、次のようなことは改める必要があります。~~

~~- `var YourModule = {};` などとして、外部から `YourModule.hoge();` などと呼び出す書き方
- `this === window` だと思うこと~~

~~今回は、これらに対応出来るような行儀の良い JavaScript モジュールの書き方を、uupaa 氏の [WebModulePattern](https://github.com/uupaa/WebModule/wiki/WebModulePattern) から端折りつつご紹介します。~~

~~ちなみに JavaScript あまり書かないのでほとんど自分用の勉強メモです。~~

~~書き方~~
---

~~まず、全体を `(function(){...})();` で囲みます。
これで `var` がグローバルを汚染しないようになります。~~

```js
(function() {
    // ...
})();
```

~~`"use strict";` を宣言しておきます。 (use strict の効用: http://qiita.com/Jxck_/items/fe8a1c49cac717e52ae3#js-%E7%B7%A8)~~

```js
(function() {
    "use strict";
    
    // ...
})();
```

~~次に、ブラウザでも Web Worker でも node.js でも使えるような書き方でグローバルオブジェクトを取得します。~~

```js
(function(global) {
    "use strict";
    
    // ...
})((this || 0).self || global);
```

~~この idiom で、ブラウザであれば `window`, Web Workers であれば `WorkerGlobalScope`, node であれば `global` を取得出来ます。
詳しくは [WebModuleIdiom](https://github.com/uupaa/WebModule/wiki/WebModuleIdiom) を参照ください。~~

> ~~補足:  
> global 汚染が出来てしまいますが、`global.XX = XX` といった書き方をしない限り、グローバル空間を触れないという違いがあります。
> `(function(){})();` で囲わないと、`var XX = XX;` とするだけでグローバルが汚染されます。~~

~~この中で、実行環境を特定したい場合は、次の idiom を使います。~~

```js
var isBrowser = "document" in global;
var isWebWorkers = "WorkerLocation" in global;
var isNode = "process" in global; 
```

~~次に、CommonJS スタイルでの `require` に対応するため、`module.exports` にモジュールをエクスポートします。
最近では node.js だけではなく、ブラウザでも browserify や webpack を利用して `require` を使えるため、ブラウザだけの対応でもエクスポートを行ないます。~~

```js
if ("process" in global) {
   module.exports = YourModule;
}
```

~~最後に、CommonJS スタイルでない通常の `<script>` 読み出しに対応する為、global オブジェクトに Module を突っ込みます。~~

```js
global["YourModule"] = YourModule;
```

~~全体~~

```js
(function(global) {
    "use strict;"

    // Your Module
    function YourModule() {
        // ...
    };

    // Exports
    if ("process" in global) {
        module["exports"] = YourModule;
    }
    global["YourModule"] = YourModule;

})((this || 0).self || global);
```

~~これで最低限まともにエクスポートされるコードが完成しました。
長いように見えますが、過度期なので仕方がありません。
テンプレとしてどこかに保持しておけば良いでしょう。~~

~~ヘッダーと実装の分離~~
---

~~JS には `.h` がありません。
ですから、ソースを読む側からするとどんなメソッドがあるかを知るだけでも一苦労ですね…~~

~~`YourModule.prototype.someMethod = function() {...}` とすると、実装も宣言も全て一緒くたに書かれてしまうので分離します。~~

> ~~補足:  
> ややこしいですが `someMethod = function() {}` と書くと関数自体が無名関数になってしまい、プロファイラ等での追跡が困難になるなどの欠点もあります。~~

~~実装は `function method()` の関数宣言のスタイルで行い、`YourModule.prototype.method = method;` としてヘッダーとします。~~

```js
// Class
function YourModule() {
}

// Header
YourModule["prototype"]["constructor"] = YourModule;
YourModule["prototype"]["method"] = method;

// Implementation
function YourModule_method(someArg) {
    // ...
}
```

~~このままでは Header を見ても引数が分からないので、コメントで足します。~~

```js
YourModule["prototype"]["method"] = method; // YourModule#method(someArg:any):void
```

~~コメントのスタイルは好みで何でも良いです。ちなみにこれは同じく uupaa 氏作の [Help.js スタイル](https://github.com/uupaa/Help.js/wiki/Help)です。~~

まとめ
---

~~以上、次のようなスタイルで書いていけば行儀の良いモジュールの書き方が出来ます。~~

```js
(function(global) {
    "use strict;"

    // Class ------------------------------------------------
    function YourModule() {
    };

    // Header -----------------------------------------------
    YourModule["prototype"]["method"] = YourModule_method; // YourModule#method(someArg:any):void

    // Implementation ---------------------------------------
    function YourModule_method(someArg) {
        // ...
    }

    // Exports ----------------------------------------------
    if ("process" in global) {
        module["exports"] = YourModule;
    }
    global["YourModule"] = YourModule;

})((this || 0).self || global);
```

~~すごく idiomatic ですが、テンプレだと思えば…~~

Further Reading
---

この書き方の原典です。より詳しく乗っています。（実は、WebModulePattern では global に突っ込む書き方にもう一工夫あります。端折ってしまいました。）
-> [WebModulePattern · uupaa/WebModule Wiki](https://github.com/uupaa/WebModule/wiki/WebModulePattern)

最近の JS を知りたい場合は
-> [IE10 以下を切る場合の JavaScript チェックリスト](http://qiita.com/Jxck_/items/fe8a1c49cac717e52ae3)

Browserify についてサクッと知りたい場合は
-> [Browserify: それはrequire()を使うための魔法の杖](http://qiita.com/cognitom/items/4c63969b5085c90639d4)

References
---

- WebModulePattern · uupaa/WebModule Wiki : https://github.com/uupaa/WebModule/wiki/WebModulePattern
- IE10 以下を切る場合の JavaScript チェックリスト - Qiita : http://qiita.com/Jxck_/items/fe8a1c49cac717e52ae3
- Browserify: それはrequire()を使うための魔法の杖 - Qiita : http://qiita.com/cognitom/items/4c63969b5085c90639d4