JavaScript 設(shè)計(jì)模式 安全沙箱模式
命名空間
JavaScript本身中沒(méi)有提供命名空間機(jī)制,所以為了避免不同函數(shù)、對(duì)象以及變量名對(duì)全局空間的污染,通常的做法是為你的應(yīng)用程序或者庫(kù)創(chuàng)建一個(gè)唯一的全局對(duì)象,然后將所有方法與屬性添加到這個(gè)對(duì)象上。
/* 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)建了一個(gè)全局對(duì)象MYAPP,并將其他所有對(duì)象、函數(shù)作為屬性附加到MYAPP上.
通常這是一種較好的避免命名沖突的方法,它被應(yīng)用在很多項(xiàng)目中,但這種方法有一些缺點(diǎn)。
1.需要給所有需要添加的函數(shù)、變量加上前綴。
2.因?yàn)橹挥幸粋€(gè)全局對(duì)象,這意味著一部分代碼可以肆意地修改全局對(duì)象而導(dǎo)致其余代碼的被動(dòng)更新。
全局構(gòu)造器
你可以用一個(gè)全局構(gòu)造器,而不是一個(gè)全局對(duì)象,我們給這個(gè)構(gòu)造器起名為Sandbox(),你可以用這個(gè)構(gòu)造器創(chuàng)建對(duì)象,你還可以為構(gòu)造器傳遞一個(gè)回調(diào)函數(shù)作為參數(shù),這個(gè)回調(diào)函數(shù)就是你存放代碼的獨(dú)立沙箱環(huán)境。
new Sandbox(function(box){
// your code here...
});
代碼清單2:沙箱的使用
讓我們給沙箱添加點(diǎn)別的特性
1.創(chuàng)建沙箱時(shí)可以不使用'new'操作符
2.Sandbox()構(gòu)造器接受一些額外的配置參數(shù),這些參數(shù)定義了生成對(duì)象所需模塊的名稱,我們希望代碼更加模塊化。
擁有了以上特性后,讓我們看看怎樣初始化一個(gè)對(duì)象。
代碼清單3顯示了你可以在不需要‘new'操作符的情況下,創(chuàng)建一個(gè)調(diào)用了'ajax'和'event'模塊的對(duì)象.
Sandbox(['ajax', 'event'], function(box){
// console.log(box);
});
代碼清單3:以數(shù)組的形式傳遞模塊名
Sandbox('ajax', 'dom', function(box){
// console.log(box);
});
代碼清單4:以獨(dú)立的參數(shù)形式傳遞模塊名
代碼清單5顯示了你可以把通配符'*'作為參數(shù)傳遞給構(gòu)造器,這意味著調(diào)用所有可用的模塊,為了方便起見(jiàn),如果沒(méi)有向構(gòu)造器傳遞任何模塊名作為參數(shù),構(gòu)造器會(huì)把'*'作為缺省參數(shù)傳入.
Sandbox('*', function(box){
// console.log(box);
});
Sandbox(function(box){
// console.log(box);
});
代碼清單5:調(diào)用所用可用模塊
代碼清單6顯示你可以初始化沙箱對(duì)象多次,甚至你可以嵌套它們,而不用擔(dān)心彼此間會(huì)產(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:嵌套的沙箱實(shí)例
從上面這些示例可以看出,使用沙箱模式,通過(guò)把所有代碼邏輯包裹在一個(gè)回調(diào)函數(shù)中,你根據(jù)所需模塊的不同生成不同的實(shí)例,而這些實(shí)例彼此互不干擾獨(dú)立的工作著,從而保護(hù)了全局命名空間。
現(xiàn)在讓我們看看怎樣實(shí)現(xiàn)這個(gè)Sandbox()構(gòu)造器.
添加模塊
在實(shí)現(xiàn)主構(gòu)造器之前,讓我們看看如何向Sandbox()構(gòu)造器中添加模塊。
因?yàn)镾andbox()構(gòu)造器函數(shù)也是對(duì)象,所以你可以給它添加一個(gè)名為'modules'的屬性,這個(gè)屬性將是一個(gè)包含一組鍵值對(duì)的對(duì)象,其中每對(duì)鍵值對(duì)中Key是需要注冊(cè)的模塊名,而Value則是該模塊的入口函數(shù),當(dāng)構(gòu)造器初始化時(shí)當(dāng)前實(shí)例會(huì)作為第一個(gè)參數(shù)傳遞給入口函數(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:注冊(cè)模塊
實(shí)現(xiàn)構(gòu)造器
代碼清單8描述了實(shí)現(xiàn)構(gòu)造器的方法,其中關(guān)鍵的幾個(gè)要點(diǎn):
1.我們檢查this是否為Sandbox的實(shí)例,若不是,證明Sandbox沒(méi)有被new操作符調(diào)用,我們將以構(gòu)造器方式重新調(diào)用它。
2.你可以在構(gòu)造器內(nèi)部為this添加屬性,同樣你也可以為構(gòu)造器的原型添加屬性。
3.模塊名稱會(huì)以數(shù)組、獨(dú)立參數(shù)、通配符‘*'等多種形式傳遞給構(gòu)造器。
4.請(qǐng)注意在這個(gè)例子中我們不需要從外部文件中加載模塊,但在諸如YUI3中,你可以僅僅加載基礎(chǔ)模塊(通常被稱作種子(seed)),而其他的所有模塊則會(huì)從外部文件中加載。
5.一旦我們知道了所需的模塊,并初始化他們,這意味著調(diào)用了每個(gè)模塊的入口函數(shù)。
6.回調(diào)函數(shù)作為參數(shù)被最后傳入構(gòu)造器,它將使用最新生成的實(shí)例并在最后執(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:實(shí)現(xiàn)Sandbox構(gòu)造器
原文來(lái)自:Stoyan Stefanov - JavaScript Patterns Part 7:The Sandbox Pattern
- JavaScript事件發(fā)布/訂閱模式原理與用法分析
- JavaScript實(shí)現(xiàn)與使用發(fā)布/訂閱模式詳解
- JavaScript中發(fā)布/訂閱模式的簡(jiǎn)單實(shí)例
- JS前端設(shè)計(jì)模式之發(fā)布訂閱模式詳解
- js 發(fā)布訂閱模式的實(shí)例講解
- JavaScript設(shè)計(jì)模式之觀察者模式(發(fā)布訂閱模式)原理與實(shí)現(xiàn)方法示例
- JavaScript設(shè)計(jì)模式之觀察者模式與發(fā)布訂閱模式詳解
- 詳解JavaScript設(shè)計(jì)模式中的享元模式
- JavaScript設(shè)計(jì)模式之單例模式應(yīng)用場(chǎng)景案例詳解
- JavaScript設(shè)計(jì)模式之觀察者模式(發(fā)布者-訂閱者模式)
- javascript 發(fā)布-訂閱模式 實(shí)例詳解
相關(guān)文章
js面向?qū)ο笤O(shè)計(jì)用{}好還是function(){}好(構(gòu)造函數(shù))
js面向?qū)ο笤O(shè)計(jì)用{}好還是function(){}好,大家給予了回復(fù),感覺(jué)不錯(cuò),特分享給大家。2011-10-10JavaScript 常見(jiàn)對(duì)象類創(chuàng)建代碼與優(yōu)缺點(diǎn)分析
這幾種javascript類定義方式中,最常用的是雜合prototype/constructor 和 動(dòng)態(tài)prototype方式。2009-12-12JavaScript面向?qū)ο笤O(shè)計(jì)二 構(gòu)造函數(shù)模式
在Javascript面向?qū)ο笤O(shè)計(jì)一——工廠模式 中介紹了使用CreateEmployee()函數(shù)創(chuàng)建員工類。ECMAScript中的構(gòu)造函數(shù)可以用來(lái)創(chuàng)建特定類型的對(duì)象,如Object和Array這樣的原生構(gòu)造函數(shù),在運(yùn)行時(shí)會(huì)自動(dòng)出現(xiàn)在執(zhí)行環(huán)境中,此外也可以創(chuàng)建自定義的構(gòu)造函數(shù),從而創(chuàng)建自定義對(duì)象類型的屬性和方法2011-12-12Javascript 面向?qū)ο螅ㄒ唬?共有方法,私有方法,特權(quán)方法)
最近在網(wǎng)上盾一些JS面向?qū)ο蟮臇|西。把其他高手們總結(jié)的東西,加上自己的理解,總結(jié)一下2012-05-05javascript 對(duì)象入門(mén)實(shí)例教程
學(xué)習(xí)javascript 對(duì)象操作的朋友可以參考下,這個(gè)是入門(mén)級(jí)教程。2010-04-04