ホームページ > 記事 > ウェブフロントエンド > JavaScript SandBox サンドボックスのデザイン パターン
サンドボックス モードは、YUI3 コアで一般的で、グローバル オブジェクトの汚染を避けるために、同じコンストラクター (Constructor) を使用して独立した非干渉 (自己完結型) インスタンス オブジェクトを生成するメソッドです。
名前空間
JavaScript 自体は名前空間メカニズムを提供していないため、さまざまな関数、オブジェクト、変数名によるグローバル空間の汚染を避けるために、通常のアプローチは、アプリケーションまたはライブラリ用に一意のグローバル オブジェクトを作成することです。次に、すべてのメソッドとプロパティをこのオブジェクトに追加します。
コード リスト 1: 従来の名前空間モード
/* BEFORE: 5 globals */ // constructors function Parent() {} function Child() {} // a variable var some_var = 1; // some objects var module1 = {}; module1.data = {a: 1, b: 2}; var module2 = {}; /* AFTER: 1 global */ // global object var MYAPP = {}; // constructors MYAPP.Parent = function() {}; MYAPP.Child = function() {}; // a variable MYAPP.some_var = 1; // an object MYAPP.modules = {}; // nested objects MYAPP.modules.module1 = {}; MYAPP.modules.module1.data = {a: 1, b: 2}; MYAPP.modules.module2 = {};
このコードでは、グローバル オブジェクト MYAPP を作成し、他のすべてのオブジェクトと関数を属性として MYAPP にアタッチします。
通常、これは名前の競合を避けるためのより良い方法であり、多くのプロジェクトで使用されていますが、この方法にはいくつかの欠点があります。
追加する必要があるすべての関数と変数にプレフィックスを追加する必要があります。
グローバル オブジェクトは 1 つだけであるため、コードの一部がグローバル オブジェクトを任意に変更し、コードの残りの部分が受動的に更新される可能性があることを意味します。
グローバル コンストラクター
このコンストラクターを Sandbox() という名前でオブジェクトを作成することもできます。コールバック関数はパラメーターとして使用されます。コールバック関数は、コードを保存する独立したサンドボックス環境です。
コード リスト 2: サンドボックスの使用法
new Sandbox(function(box){ // your code here... });
サンドボックスに他の機能を追加しましょう。
「new」演算子を使用せずにサンドボックスを作成できます。
Sandbox() コンストラクターは、オブジェクトの生成に必要なモジュールの名前を定義する追加の構成パラメーターを受け入れます。コードをよりモジュール化したいと考えています。
上記の機能を備えた後、オブジェクトを初期化する方法を見てみましょう。
コード リスト 3 は、「new」演算子を必要とせずに「ajax」モジュールと「event」モジュールを呼び出すオブジェクトを作成できることを示しています。
コード リスト 3: モジュール名を配列として渡す
Sandbox(['ajax', 'event'], function(box){ // console.log(box); });
コード リスト 4: モジュール名を別のパラメーターとして渡す
Sandbox('ajax', 'dom', function(box){ // console.log(box); });
コード リスト 5 は、ワイルドカード '*' をパラメーターとしてコンストラクターに渡すことができることを示しています。 , これは、便宜上、引数としてモジュール名がコンストラクターに渡されない場合、コンストラクターはデフォルトの引数として「*」を渡します。
コード リスト 5: 使用可能なモジュールの呼び出し
Sandbox('*', function(box){ // console.log(box); }); Sandbox(function(box){ // console.log(box); });
コード リスト 6 は、サンドボックス オブジェクトを複数回初期化できること、および相互の競合を気にせずにサンドボックス オブジェクトをネストできることを示しています。
コード リスト 6: ネストされたサンドボックス インスタンス
Sandbox('dom', 'event', function(box){ // work with dom and event Sandbox('ajax', function(box) { // another sandboxed "box" object // this "box" is not the same as // the "box" outside this function //... // done with Ajax }); // no trace of Ajax module here });
上記の例からわかるように、サンドボックス モードを使用すると、すべてのコード ロジックをコールバック関数でラップすることで、必要なモジュールに基づいてさまざまなモジュールを生成できます。これらのインスタンスは互いに干渉することなく独立して動作するため、グローバル名前空間が保護されます。
次に、この Sandbox() コンストラクターを実装する方法を見てみましょう。
モジュールの追加
メイン コンストラクターを実装する前に、Sandbox() コンストラクターにモジュールを追加する方法を見てみましょう。 Sandbox() コンストラクター関数もオブジェクトであるため、「modules」という名前の属性を追加できます。この属性は、キーと値のペアのセットを含むオブジェクトになります。各ペアのキーは名前です。登録する必要があるモジュールの値、Value はモジュールのエントリ関数です。コンストラクターが初期化されると、現在のインスタンスが最初のパラメーターとしてエントリ関数に渡されるため、エントリ関数は追加のプロパティとプロパティを追加できます。メソッドをインスタンスに追加します。
コード リスト 7 では、「dom」、「event」、「ajax」モジュールを追加しました。
コード リスト 7: 登録モジュール
Sandbox.modules = {}; Sandbox.modules.dom = function(box) { box.getElement = function() {}; box.getStyle = function() {}; box.foo = "bar"; }; Sandbox.modules.event = function(box) { // access to the Sandbox prototype if needed: // box.constructor.prototype.m = "mmm"; box.attachEvent = function(){}; box.dettachEvent = function(){}; }; Sandbox.modules.ajax = function(box) { box.makeRequest = function() {}; box.getResponse = function() {}; };
コンストラクターの実装
コード リスト 8 は、いくつかの重要なポイントを含むコンストラクターの実装方法を説明します。
これが Sandbox のインスタンスであるかどうかを確認し、そうでない場合は Sandbox If を証明します。これは new 演算子によって呼び出されないため、コンストラクターとして再度呼び出します。
コンストラクター内でこれに属性を追加できます。また、コンストラクターのプロトタイプに属性を追加することもできます。
モジュール名は、配列、独立したパラメーター、ワイルドカード文字「*」などのさまざまな形式でコンストラクターに渡されます。
この例では外部ファイルからモジュールをロードする必要はありませんが、YUI3 などのシステムでは、基本モジュール (シードと呼ばれることが多い) のみをロードでき、他のすべてのモジュールは外部ファイルからロードされることに注意してください。 . ファイルにロードされます。
一旦我们知道了所需的模块,并初始化他们,这意味着调用了每个模块的入口函数。
回调函数作为参数被最后传入构造器,它将使用最新生成的实例并在最后执行。
代码清单8:实现Sandbox构造器
<script> function Sandbox() { // turning arguments into an array var args = Array.prototype.slice.call(arguments), // the last argument is the callback callback = args.pop(), // modules can be passed as an array or as individual parameters modules = (args[0] && typeof args[0] === "string") ? args : args[0], i; // make sure the function is called // as a constructor if (!(this instanceof Sandbox)) { return new Sandbox(modules, callback); } // add properties to 'this' as needed: this.a = 1; this.b = 2; // now add modules to the core 'this' object // no modules or "*" both mean "use all modules" if (!modules || modules === '*') { modules = []; for (i in Sandbox.modules) { if (Sandbox.modules.hasOwnProperty(i)) { modules.push(i); } } } // init the required modules for (i = 0; i < modules.length; i++) { Sandbox.modules[modules[i]](this); } // call the callback callback(this); } // any prototype properties as needed Sandbox.prototype = { name: "My Application", version: "1.0", getName: function() { return this.name; } }; </script>