JavaScript SandBox サンドボックスのデザイン パターン

高洛峰
リリース: 2016-11-28 15:40:22
オリジナル
1464 人が閲覧しました

サンドボックス モードは、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 &#39;this&#39; as needed:
    this.a = 1;
    this.b = 2;
    // now add modules to the core &#39;this&#39; object
    // no modules or "*" both mean "use all modules"
    if (!modules || modules === &#39;*&#39;) {
        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>
ログイン後にコピー


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート