JavaScript SandBox沙箱设计模式

沙箱模式常见于YUI3 core,它是一种采用同一构造器(Constructor)生成彼此独立且互不干扰(self-contained)的实例对象,而从避免污染全局对象的方法。

命名空间

JavaScript本身中没有提供命名空间机制,所以为了避免不同函数、对象以及变量名对全局空间的污染,通常的做法是为你的应用程序或者库创建一个唯一的全局对象,然后将所有方法与属性添加到这个对象上。缙云县外国专家局

代码清单1 : 传统命名空间模式

01 /* BEFORE: 5 globals */
02 // constructors
03 function Parent() {}
04 function Child() {}
05 // a variable
06 var some_var = 1;
07 // some objects
08 var module1 = {};
09 module1.data = {a: 1, b: 2};
10 var module2 = {};
11 /* AFTER: 1 global */
12 // global object
13 var MYAPP = {};
14 // constructors
15 MYAPP.Parent = function() {};
16 MYAPP.Child = function() {};
17 // a variable
18 MYAPP.some_var = 1;
19 // an object
20 MYAPP.modules = {};
21 // nested objects
22 MYAPP.modules.module1 = {};
23 MYAPP.modules.module1.data = {a: 1, b: 2};
24 MYAPP.modules.module2 = {};

在这段代码中,你创建了一个全局对象MYAPP,并将其他所有对象、函数作为属性附加到MYAPP上。

通常这是一种较好的避免命名冲突的方法,它被应用在很多项目中,但这种方法有一些缺点。

  • 需要给所有需要添加的函数、变量加上前缀。
  • 因为只有一个全局对象,这意味着一部分代码可以肆意地修改全局对象而导致其余代码的被动更新。

全局构造器

你可以用一个全局构造器,而不是一个全局对象,我们给这个构造器起名为Sandbox(),你可以用这个构造器创建对象,你还可以为构造器传递一个回调函数作为参数,这个回调函数就是你存放代码的独立沙箱环境。

代码清单2:沙箱的使用

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

让我们给沙箱添加点别的特性。

  1. 创建沙箱时可以不使用‘new‘操作符。
  2. Sandbox()构造器接受一些额外的配置参数,这些参数定义了生成对象所需模块的名称,我们希望代码更加模块化。

拥有了以上特性后,让我们看看怎样初始化一个对象。

代码清单3显示了你可以在不需要‘new’操作符的情况下,创建一个调用了‘ajax‘和‘event‘模块的对象。

代码清单3:以数组的形式传递模块名

1 Sandbox([‘ajax‘‘event‘], function(box){
2     // console.log(box);
3 });

代码清单4:以独立的参数形式传递模块名

1 Sandbox(‘ajax‘‘dom‘function(box){
2     // console.log(box);
3 });

代码清单5显示了你可以把通配符‘*‘作为参数传递给构造器,这意味着调用所有可用的模块,为了方便起见,如果没有向构造器传递任何模块名作为参数,构造器会把‘*‘作为缺省参数传入。

代码清单5:调用所用可用模块

1 Sandbox(‘*‘function(box){
2     // console.log(box);
3 });
4 Sandbox(function(box){
5     // console.log(box);
6 });

代码清单6显示你可以初始化沙箱对象多次,甚至你可以嵌套它们,而不用担心彼此间会产生任何冲突。

代码清单6:嵌套的沙箱实例

01 Sandbox(‘dom‘‘event‘function(box){
02     // work with dom and event
03     Sandbox(‘ajax‘function(box) {
04     // another sandboxed "box" object
05     // this "box" is not the same as
06     // the "box" outside this function
07     //...
08     // done with Ajax
09     });
10     // no trace of Ajax module here
11 });

从上面这些示例可以看出,使用沙箱模式,通过把所有代码逻辑包裹在一个回调函数中,你根据所需模块的不同生成不同的实例,而这些实例彼此互不干扰独立的工作着,从而保护了全局命名空间。

现在让我们看看怎样实现这个Sandbox()构造器。

添加模块

在实现主构造器之前,让我们看看如何向Sandbox()构造器中添加模块。

因为Sandbox()构造器函数也是对象,所以你可以给它添加一个名为’modules‘的属性,这个属性将是一个包含一组键值对的对象,其中每对键值对中Key是需要注册的模块名,而Value则是该模块的入口函数,当构造器初始化时当前实例会作为第一个参数传递给入口函数,这样入口函数就能为该实例添加额外的属性与方法。

在代码清单7中,我们添加了‘dom‘,‘event‘,‘ajax‘模块。

代码清单7:注册模块

01 Sandbox.modules = {};
02 Sandbox.modules.dom = function(box) {
03     box.getElement = function() {};
04     box.getStyle = function() {};
05     box.foo = "bar";
06 };
07 Sandbox.modules.event = function(box) {
08     // access to the Sandbox prototype if needed:
09     // box.constructor.prototype.m = "mmm";
10     box.attachEvent = function(){};
11     box.dettachEvent = function(){};
12 };
13 Sandbox.modules.ajax = function(box) {
14     box.makeRequest = function() {};
15     box.getResponse = function() {};
16 };

实现构造器

代码清单8描述了实现构造器的方法,其中关键的几个要点:

  1. 我们检查this是否为Sandbox的实例,若不是,证明Sandbox没有被new操作符调用,我们将以构造器方式重新调用它。
  2. 你可以在构造器内部为this添加属性,同样你也可以为构造器的原型添加属性。
  3. 模块名称会以数组、独立参数、通配符‘*’等多种形式传递给构造器。
  4. 请注意在这个例子中我们不需要从外部文件中加载模块,但在诸如YUI3中,你可以仅仅加载基础模块(通常被称作种子(seed)),而其他的所有模块则会从外部文件中加载。
  5. 一旦我们知道了所需的模块,并初始化他们,这意味着调用了每个模块的入口函数。
  6. 回调函数作为参数被最后传入构造器,它将使用最新生成的实例并在最后执行。

代码清单8:实现Sandbox构造器

01 <script>
02 function Sandbox() {
03     // turning arguments into an array
04     var args = Array.prototype.slice.call(arguments),
05     // the last argument is the callback
06     callback = args.pop(),
07     // modules can be passed as an array or as individual parameters
08     modules = (args[0] && typeof args[0] === "string") ?
09     args : args[0],
10     i;
11     // make sure the function is called
12     // as a constructor
13     if (!(this instanceof Sandbox)) {
14         return new Sandbox(modules, callback);
15     }
16     // add properties to ‘this‘ as needed:
17     this.a = 1;
18     this.b = 2;
19     // now add modules to the core ‘this‘ object
20     // no modules or "*" both mean "use all modules"
21     if (!modules || modules === ‘*‘) {
22         modules = [];
23             for (i in Sandbox.modules) {
24                 if (Sandbox.modules.hasOwnProperty(i)) {
25                     modules.push(i);
26             }
27         }
28     }
29     // init the required modules
30     for (i = 0; i < modules.length; i++) {
31         Sandbox.modules[modules[i]](this);
32     }
33     // call the callback
34     callback(this);
35 }
36 // any prototype properties as needed
37 Sandbox.prototype = {
38     name: "My Application",
39     version: "1.0",
40     getName: function() {
41         return this.name;
42     }
43 };
44 </script>
时间: 2024-08-25 10:15:42

JavaScript SandBox沙箱设计模式的相关文章

一种JavaScript 类的设计模式

一种JavaScript 类的设计模式尽管前面介绍了如何定义一个类,如何初始化一个类的实例,但既可以在function定义的函数体中添加成员,又可以用prototype 定义类的成员,代码显的很混乱,和面向对象语言类的实现之间有着很大的区别.那么,如何以一种清晰的方式来定义类呢?下面给出了一种类的实现模式,并将它们对应到面向对象语言类的实现上.类的构造函数用来初始化一个实例,是每个类必不可少的一部分.在传统意义的面向对象中,类的构造函数的名称和类的名称一致,同时它们的定义方式和类成员的定义是类似

javascript常见的设计模式举例

    近日重读<javascript面型对象编程指南>这本书,最后一章介绍了常见的javascript设计模式的实现.主要讲解了四种设计模式:单例模式.工厂模式.装饰器模式和观察者模式.js作为动态语言,实现这四种模式的实例相对简单,当然既然称之为模式,那么吃透思想更重要,那么下面,由乐帝来实例讲解四种模式.    1.单例模式    顾名思义,对象构造出来的是实例,从字面上理解,单例即单实例,这意味一个类只能创建一个实例对象.当需要创建一种类型或者一个类的唯一对象时,可使用该模式.以下两个

关于JavaScript的沙箱模式

从语言学的角度上来说,允许代码无节制地使用全局变量,是最错误的选择之一.而更可怕的,就是一个变量"可能"成为全局的(在未知的时间与地点).但是这两项,却伴随JavaScript这门语言成功地走到了现在.定州市科技工业局 也许是限于浏览器应用的规模,所以这一切还迟迟没有酿成灾难.在此之前,出现了两种解决方案.一种是ECMA在新的规范(Edition 5)中对此做出了限制,其中最重要的一条便是eval()的使用变得不再随意和无度.而另一种方案,则是相对没有那么官僚与学术的,尽管也拥有一个同

写的一个轻量级javascript框架的设计模式

公司一直使用jQuery框架,一些小的项目还是觉得jQuery框架太过于强大了,于是自己周末有空琢磨着写个自己的框架.谈到js的设计模式,不得不说说js的类继承机制,javascript不同于PHP可以轻松的实现类继承,不过javascript的类继承方法还是有的,常见的有构建函数.原型扩展.综合……,也有一些专门写类的函数,例如jQuery的作者有个类继承函数.关于类继承写法可以简单看 ______________________________________________________

Javascript常用的设计模式详解

阅读目录 一:理解工厂模式 二:理解单体模式 三:理解模块模式 四:理解代理模式 五:理解职责链模式 六:命令模式的理解: 七:模板方法模式 八:理解javascript中的策略模式 九:Javascript中理解发布--订阅模式 十:理解中介者模式 回到顶部 一:理解工厂模式 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式. 简单的工厂模式可以理解为解决多个相似的问题;这也是她的优点;比如如下代码: function CreateP

javaScript几种设计模式之一——单体模式

javaScript是一种弱类型.动态的.基于原型的语言,这种语言特性使得它非常容易. 甚至是普通的方式实现其中的一些模式. 单体模式的思想在于保证一个特定类仅有一个实例.这就意味着当您第二次使用同一个 类创建新对象的时候,应该得到与第一次所创建对象完全相同对象. 在javaScript中没有类,只有对象.当您创建一个新对象时,实际上没有其他对象与其 类似,因此新对象已经是单体了.使用对象字面量创建一个简单的对象也是一个单体的 例子. var obj ={ myprop:'my value' }

JavaScript中的设计模式:单例模式

定义 单例模式就是一个类只能实例化一个对象,并且提供了一个访问它的全局访问点. 一般在实现登陆框,或者一个全局的控制器都会用到单例模式.现实中有window对象,线程池,全局缓存等. 简单实现 var Person = function(name){ this.name = name; this.instance = null; }; Person.getInstance = function(name){ if(!this.instance){ this.instance = new Pers

浅谈javascript之经典设计模式——观察者模式

观察者模式简介: 观察者模式又被称为发布订阅模式.是一种一对多的依赖关系,也就是某一个对象(消息发布者)的状态发生改变时,其他的对象(订阅者)接收到消息后会自动执行各自的操作. 该模式中涉及到的对象: 1.消息发布者(一个) 1.1消息发布者首先会建立一个通知数组arr,用来存储订阅者信息对象(有订阅该消息的观察者obj以及obj对应操作的回调函数callback) 1.2消息发布者角色职责: (1)制定订阅该消息的方法 (2)制定取消订阅消息的放方法 (3)消息发布 2.订阅者(众多):订阅者

JavaScript中的设计模式:状态模式

前几天写了一个贪吃蛇小游戏,正好用到了状态模式. 定义 当一个对象内部状态发生改变时候,会导致其行为的改变,这看起来像是改变了对象. 简单的例子 如果一个函数要更具某一个对象的状态来判断该对象应该执行的方法,那么这个函数中会增加很多if判断分支,并且,如果要增加这个对象的一种状态,那么就要在原来的代码中添加一些判断,比较麻烦.例如,贪吃蛇有移动.吃食物.死亡等状态,如果我在处理这些状态的时候这么写代码(如下面) this.process = function(point){ if (this.i