欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript 設計模式 安全沙箱模式

 更新時間:2010年09月24日 12:13:20   作者:  
沙箱模式常見于YUI3 core,它是一種采用同一構(gòu)造器(Constructor)生成彼此獨立且互不干擾(self-contained)的實例對象,而從避免污染全局對象的方法

命名空間

  JavaScript本身中沒有提供命名空間機制,所以為了避免不同函數(shù)、對象以及變量名對全局空間的污染,通常的做法是為你的應用程序或者庫創(chuàng)建一個唯一的全局對象,然后將所有方法與屬性添加到這個對象上。

復制代碼 代碼如下:

/* 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 = {};

代碼清單1 : 傳統(tǒng)命名空間模式


  在這段代碼中,你創(chuàng)建了一個全局對象MYAPP,并將其他所有對象、函數(shù)作為屬性附加到MYAPP上.

  通常這是一種較好的避免命名沖突的方法,它被應用在很多項目中,但這種方法有一些缺點。

  1.需要給所有需要添加的函數(shù)、變量加上前綴。
  2.因為只有一個全局對象,這意味著一部分代碼可以肆意地修改全局對象而導致其余代碼的被動更新。

  全局構(gòu)造器

  你可以用一個全局構(gòu)造器,而不是一個全局對象,我們給這個構(gòu)造器起名為Sandbox(),你可以用這個構(gòu)造器創(chuàng)建對象,你還可以為構(gòu)造器傳遞一個回調(diào)函數(shù)作為參數(shù),這個回調(diào)函數(shù)就是你存放代碼的獨立沙箱環(huán)境。
復制代碼 代碼如下:

new Sandbox(function(box){
   // your code here...
});

代碼清單2:沙箱的使用


  讓我們給沙箱添加點別的特性


  1.創(chuàng)建沙箱時可以不使用'new'操作符

  2.Sandbox()構(gòu)造器接受一些額外的配置參數(shù),這些參數(shù)定義了生成對象所需模塊的名稱,我們希望代碼更加模塊化。


  擁有了以上特性后,讓我們看看怎樣初始化一個對象。


  代碼清單3顯示了你可以在不需要‘new'操作符的情況下,創(chuàng)建一個調(diào)用了'ajax'和'event'模塊的對象.


復制代碼 代碼如下:

Sandbox(['ajax', 'event'], function(box){
   // console.log(box);
});

代碼清單3:以數(shù)組的形式傳遞模塊名
復制代碼 代碼如下:

Sandbox('ajax', 'dom', function(box){
   // console.log(box);
});

代碼清單4:以獨立的參數(shù)形式傳遞模塊名

  代碼清單5顯示了你可以把通配符'*'作為參數(shù)傳遞給構(gòu)造器,這意味著調(diào)用所有可用的模塊,為了方便起見,如果沒有向構(gòu)造器傳遞任何模塊名作為參數(shù),構(gòu)造器會把'*'作為缺省參數(shù)傳入.

復制代碼 代碼如下:

Sandbox('*', function(box){
   // console.log(box);
});
Sandbox(function(box){
   // console.log(box);
});

代碼清單5:調(diào)用所用可用模塊


  代碼清單6顯示你可以初始化沙箱對象多次,甚至你可以嵌套它們,而不用擔心彼此間會產(chǎn)生任何沖突.
復制代碼 代碼如下:

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
});

代碼清單6:嵌套的沙箱實例

  從上面這些示例可以看出,使用沙箱模式,通過把所有代碼邏輯包裹在一個回調(diào)函數(shù)中,你根據(jù)所需模塊的不同生成不同的實例,而這些實例彼此互不干擾獨立的工作著,從而保護了全局命名空間。

  現(xiàn)在讓我們看看怎樣實現(xiàn)這個Sandbox()構(gòu)造器.


  添加模塊

  在實現(xiàn)主構(gòu)造器之前,讓我們看看如何向Sandbox()構(gòu)造器中添加模塊。

  因為Sandbox()構(gòu)造器函數(shù)也是對象,所以你可以給它添加一個名為'modules'的屬性,這個屬性將是一個包含一組鍵值對的對象,其中每對鍵值對中Key是需要注冊的模塊名,而Value則是該模塊的入口函數(shù),當構(gòu)造器初始化時當前實例會作為第一個參數(shù)傳遞給入口函數(shù),這樣入口函數(shù)就能為該實例添加額外的屬性與方法。

  在代碼清單7中,我們添加了'dom','event','ajax'模塊。

復制代碼 代碼如下:

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() {};
};

代碼清單7:注冊模塊


  實現(xiàn)構(gòu)造器

  代碼清單8描述了實現(xiàn)構(gòu)造器的方法,其中關(guān)鍵的幾個要點:

  1.我們檢查this是否為Sandbox的實例,若不是,證明Sandbox沒有被new操作符調(diào)用,我們將以構(gòu)造器方式重新調(diào)用它。
  2.你可以在構(gòu)造器內(nèi)部為this添加屬性,同樣你也可以為構(gòu)造器的原型添加屬性。
  3.模塊名稱會以數(shù)組、獨立參數(shù)、通配符‘*'等多種形式傳遞給構(gòu)造器。
  4.請注意在這個例子中我們不需要從外部文件中加載模塊,但在諸如YUI3中,你可以僅僅加載基礎(chǔ)模塊(通常被稱作種子(seed)),而其他的所有模塊則會從外部文件中加載。
  5.一旦我們知道了所需的模塊,并初始化他們,這意味著調(diào)用了每個模塊的入口函數(shù)。
  6.回調(diào)函數(shù)作為參數(shù)被最后傳入構(gòu)造器,它將使用最新生成的實例并在最后執(zhí)行。
復制代碼 代碼如下:

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;
  }
};

代碼清單8:實現(xiàn)Sandbox構(gòu)造器
原文來自:Stoyan Stefanov - JavaScript Patterns Part 7:The Sandbox Pattern

相關(guān)文章

最新評論