複数のモジュールと、たとえばjQueryまたはCDN内の他のライブラリで構成されるプロジェクトがあるとします。 ユーザーにグローバル変数を表示せず、可能であればjQueryと$を表示しないことを強く望んでいます。 もちろん、プロジェクトコードを変更せずにすべてを行います。
グローバルを非表示にする理由は異なる場合があります。美しさ、セキュリティ上の理由、コード分析の難しさなどです。 ユーザーは、自分が破ることができないイベントを使用してコードを操作します。他に何も必要ありません。
最も明白な方法は、他のオブジェクトを受動的にエクスポートする単一の名前空間を作成し、最後にjQueryと$を削除することです。
アセンブリ後、コードは次のようになります。
(function(window, undefined){
これは理想的ですが、大抵はそうではありません。 あなたのコードを見て、そうですか?
アンダーカットは、単一のグローバル変数なしで任意のコードを収集できる汎用ソリューションです。
コンセプトアクティブ/パッシブインポート/エクスポート
アクティブなエクスポート (function (window) { var ModuleA = {};
ModuleAモジュールはアクティブにエクスポートされますパッシブエクスポート var ModuleC = (function (window) { var ModuleC = {};
ModuleCモジュールは受動的にエクスポートされますアクティブなインポート (function (window, $) { console.log($); }(this, jQuery));
JQueryモジュールはアクティブにインポートされますパッシブインポート (function (window) { console.log(ModuleC); }(this));
ModuleCモジュールは受動的にインポートされます組立
とにかくインポート/エクスポートするモジュールがいくつかあります。 それぞれが使用するモジュールを知っています。 各モジュールをクロージャでラップして、使用するすべてのオブジェクトのリストを転送できます。 確かに、小さな問題があります:モジュールAがモジュールBを使用し、モジュールBがモジュールAを使用し、それらがすべて直列に接続されている場合、ループにラップされたモジュールAを接続すると、ReferenceErrorエラーが発生します-モジュールBはまだありません この問題は、モジュールBをロードした後にオブジェクトを回路Aに転送することで解決します。モジュールが受動的にエクスポートされ、回路でラップすると、グローバル変数は消えます。 この問題は、ローカル変数をグローバルコンテキストに転送することで解決されます。
スクリプトの初期化中に作成したグローバル変数のリストを知っています-グローバルをクリアするには、deleteを使用してそれらを削除します。
例
ランダムにインポート/エクスポートするjQueryと3つのモジュールで構成されるサンプルプロジェクトを見てみましょう。
モジュールリスト
モジュールは、jQuery個別、ModuleA + ModuleC + ModuleDの順序で接続されます。 モジュールAはモジュールCに依存し、モジュールCはモジュールAに依存します(上記の競合)。 モジュールAは積極的にエクスポートし、モジュールCはそれ自体を受動的にエクスポートし、モジュールDは何もエクスポートしません。
集める
変数キャプチャの問題
このソリューションは、コードを分析し、不必要な変数のグローバルコンテキストをクリアすることを難しくするだけです(美しさのため)。
スクリプト(通常のユーザースクリプトまたは拡張機能)を接続する前に組み込まれたスクリプトが、watch、__ defineSetter __、ES5 setを使用して、場合によっては最小setIntervalを介して削除する前に、ModuleAおよびModuleオブジェクトをインターセプトできることは秘密ではありません。
この問題には3つの解決策があります。
1.アクティブなエクスポートを使用しないでください(キャプチャの機会はゼロです。コードを変更する必要があります)
2.グローバル変数にランダムな名前を使用します(キャプチャチャンスはゼロになる傾向があるため、コードを変更する必要があります)
3.組み立てる前にオブザーバーとタイマーを削除します(キャプチャチャンスはゼロになります)
方法3を使用して、アセンブリを変更します。
これで、JavaScript Ninjaの最も洗練されたテクニック-「グローバル変数の非表示」をマスターできました!
例外
このメソッドは、特にグローバルに散らばる場合、onsmth = "..."を介してイベント呼び出しを使用する場合には役立ちません。つまり、 不十分な動作;)グローバルにオブジェクトがない場合、メソッドは機能しません。
Ninja JavaScript Builder-Ninjs
このアセンブリメソッドの実装を書く必要がないように、私はエース-Ninjsを書きました。 これは、上記の方法を使用したJavaScriptプロジェクトビルダーです。 ビルダーは、彼の名前を正当化します-忍者として、彼はいつの間にか自分の仕事をし、トラックを整理します。
プロジェクトはgithubにあります
github.com/azproduction/ninjsNode.jsを使用してビルドします。
npmにはまだ登録されていませんが、確実に登録されます。
彼が変数のキャプチャを防ぐことができるまで-になります。
使用する
Ninjsの使用は非常に簡単です-モジュールがインポート/エクスポートする変数とそれらが存在する場所を知る必要があります。 すべてのNinjs依存関係が解決されます。
var ninjs = new (require('../Ninjs.js').Ninjs); ninjs .add({
サンプルコードとモジュールコードはこちら
github.com/azproduction/ninjs/tree/master/examplesお楽しみに。 提案、希望、批判を歓迎します!
PS私はそれをNinjsのロゴに変えるためにNinjaアイコンを探しています。