Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

RewriteToWebModulePattern

uupaa edited this pageJun 8, 2015 ·7 revisions

このエントリでは、レガシーなスタイルで書かれた JavaScript を、WebModule に使われている 実装パターン(WebModulePattern) で書き直す手順を説明します。


ES3スタイルで書かれたレガシーなコード

以下は ES3当時の古いスタイルで書かれた MyExample.js です。
MyExample をグローバル空間にエクスポートしています。

// Before (古いスタイルで書かれた、変更前のソースコード)(function(win,undefined){functionMyExample(value){this._value=value||"";}MyExample.prototype.concat=function(a){returnthis._value+a;};win.MyExample=MyExample;})(window);
<scriptsrc="MyExample.js"></script><script>newMyExample("Hello").concat("JavaScript");// "HelloJavaScript"</script>

スタイルをリライトし新しいコードに

先ほどのES3基準の古いスタイルのコードは、残念ながらブラウザ以外の環境で動作しません。頑張って全ての行を書き直す必要があります。スタイルを新しくしつつ、Node.js や WebWorkers でも動作するようにモジュール化していきます。

// for WebWorkersimportScripts("WebModule.js");importScripts("MyExample.js");newWebModule.MyExample("Hello").concat("JavaScript");// "HelloJavaScript"
// for Node.jsrequire("./WebModule.js");require("./MyExample.js");newWebModule.MyExample("Hello").concat("JavaScript");// "HelloJavaScript"

古い ES3 スタイルな MyExample.js に施す変更は以下の通りです。

  1. 先頭部分に"use strict" を追加します

    (function(win,undefined){"use strict";
  2. undefined を除去します

    • ES5 strict mode では undefined は上書きできません
    • 引数を1つ少なく渡す事で undefined を作成するアドホックなコードは lint ツールが普及する前のカビが生えた古いやり方です。削りましょう
    (function(win){"use strict";
  3. ヘッダ(宣言)とボディ(実装)が癒着しないようにコード内にコメントを追加し、ブロックを明確にします

    (function(win){"use strict";// --- dependency modules ----------------------------------// --- define / local variables ----------------------------// --- class / interfaces ----------------------------------functionMyExample(value){this._value=value||"";}// --- implements ------------------------------------------MyExample.prototype.concat=function(a){returnthis._value+a;};})(window);
  4. Node.js でも global オブジェクトが取得できるように(function(win) { ... })(window); の部分を書き換えます

    • コードの先頭にmoduleExportermoduleClosure 関数を追加します
    • ファイルの最後にreturn MyExample; } を追加します
    // before(function(win){    ...})(window);
    // after(functionmoduleExporter(name,closure){"use strict";varentity=GLOBAL["WebModule"]["exports"](name,closure);if(typeofmodule!=="undefined"){module["exports"]=entity;}returnentity;})(MyExample,functionmoduleClosure(global){"use strict";        :        :returnMyExample;// return entity});
  5. MyExample.prototype.concat = function(a) { ... }; と直書きしている function 式を
    function 文 (function MyExample_concat(a) { ... }) の形に直します

    • function 式を function 文に直すことで、メソッドの実体(Body)とAPIの宣言部(Header)を分離できます
      • DevTools のプロファイラを使ったパフォーマンス・チューニングするためにも function 文への変換が必要になります
    • 実装(Body)を implements ブロックに記述し、宣言部分(Header)を class / interfaces ブロックに記述します
    • Object.create を伴った宣言を行い、将来 getter や setter も定義できるようにしておきます
    // beforeMyExample.prototype.concat=function(a){returnthis._value+a;};
    // after// --- class / interfaces ----------------------------------MyExample.prototype=Object.create(MyExample,{constructor:{value:MyExample},concat:{value:MyExample_concat,},});// --- implements ------------------------------------------functionMyExample_concat(a){returnthis._value+a;}
  6. MyExample.repository を追加します

    • class / interfaces ブロックに、モジュールのリポジトリURL を追加します。
    • MyExample.repository の値はMyExample.help,Help("MyExample") 実行時に使用します
    // --- class / interfaces ----------------------------------functionMyExample(...){    ...}MyExample.repository="https://github.com/{GitHubユーザ名}/MyExample.js";MyExample.prototype=Object.create(MyExample,{    ...});
  7. MyExample のコンストラクタや concatメソッドにFunction Attribute を追加します

    • JavaDoc(JsDoc) スタイルは使わずValidate 形式で記述します
    • MyExample#concatMyExample.prototype.concat を省略したものです
    // --- class / interfaces ----------------------------------functionMyExample(value){//@arg String = ""this._value=value||"";}MyExample.repository="https://github.com/{GitHubユーザ名}/MyExample.js";MyExample.prototype=Object.create(MyExample,{constructor:{value:MyExample},// new MyExample(value:String = ""):MyExampleconcat:{value:MyExample_concat,},// MyExample#concat(a:String):String});// --- implements -------------------------------------------functionMyExample_concat(a){//@arg String//@ret Stringreturnthis._value+a;}
  8. $valid$type などのバリデーションコードを @dev コードブロックの内側に配置します。

    functionMyExample(value){//@arg String = ""//{@dev$valid($type(value,"String|omit"),MyExample,"value");//}@devthis._value=value||"";}// --- implements -------------------------------------------functionMyExample_concat(a){//@arg String//@ret String//{@dev$valud($type(a,"String"),MyExample_concat,"a");//}@devreturnthis._value+a;}
  9. Minifier にリネームされたくない識別子やプロパティをobject.concat のドットシンタックス形式からobject["concat"] のブラケット形式に書き換えます

    • Closure Compiler の ADVANCED_OPTIMIZATION MODE に対応するためには、この作業が必要です
    • モジュールの外部から参照する名前はリネームされないようにガードが必要です
    // beforeMyExample.prototype.concat=MyExample_concat;
    // afterMyExample["repository"]="https://github.com/{GitHubユーザ名}/MyExample.js";MyExample["prototype"]=Object.create(MyExample,{"constructor":{"value":MyExample},"concat":{"value":MyExample_concat,},});

まとめ

ここまでのコードをまとめると、こうなります。

(functionmoduleExporter(name,closure){"use strict";varentity=GLOBAL["WebModule"]["exports"](name,closure);if(typeofmodule!=="undefined"){module["exports"]=entity;}returnentity;})(MyExample,functionmoduleClosure(global){"use strict";// --- dependency modules ----------------------------------// --- define / local variables ----------------------------// --- class / interfaces ----------------------------------functionMyExample(value){//@arg String = "" - comment//{@dev$valid($type(value,"String|omit"),MyExample,"value");//}@devthis._value=value||"";}MyExample["repository"]="https://github.com/uupaa/MyExample.js";MyExample["prototype"]=Object.create(MyExample,{"constructor":{"value":MyExample},// new MyExample(value:String = ""):MyExample"concat":{"value":MyExample_concat},// MyExample#concat(a:String):String});// --- implements ------------------------------------------functionMyExample_concat(a){//@arg String//@ret String//{@dev$valud($type(a,"String"),MyExample_concat,"a");//}@devreturnthis._value+a;}returnMyExample;// return entity});
Clone this wiki locally

[8]ページ先頭

©2009-2025 Movatter.jp