沙盘模式可以弥补命名空间模式中的两项不足之处:

  • 使用唯一全局对象作为程序的全局变量入口,使得无法在同一程序中使用两个不同版本的API,因此它们使用的是同一个唯一的全局对象名,如MYAPP;
  • 较长的嵌套对象使得代码编写和解析都比较慢;
沙盘模式,正如其名字所说,提供了一个各类模块可以共同“游戏”的环境,模块之间和沙盘之间不会相互影响。
这种模式在YUI3中大量被使用。下面介绍一种沙盘模式的实现方式:
1. 全局的构造函数
在命名空间模式中只有一个全局对象;在沙盘模式中,唯一的是一个全局的构造函数:比如说,Sandbox()。Sandbox只是本例使用的名字,程序里应该使用一个有具体含义的名字。这个全局的构造函数接受一个回调函数,并为这个回调函数提供沙盘环境。
沙盘构造函数的调用大概是这样的:
new Sandbox(function (box) {
// your code here...
});
对象box就好像命名空间模式中的MYAPP,提供了程序库当中需要的功能。
然后再向沙盘模式加入两样技术:
使用之前提到的检查方法,保证总是用new来调用沙盘构造函数;
沙盘构造函数接受参数,来告知沙盘内应提供哪些模块的功能;
有了这两个技术,我们会检查出Sandbox()不用new来调用,并在Sandbox()内部再用new来调用它自己:保证它总是用new来调用的;并传入适当的参数来通知沙盘提供相应的功能。这样,Sanbox()的调用过程就变成了这样:
Sandbox(['ajax', 'event'], function (box) {
// console.log(box);
});
也可以把要在沙盘中提供的功能模块的名字分别用两个(或多个)参数传入沙盘函数:
Sandbox('ajax', 'dom', function (box) {
// console.log(box);
});
如果程序中有许多模块,并希望一次全部支持所有模块的功能,可以用“*”来代替所有的模块名字,或者更简单地,省略模块名的参数来表示需要所有模块:
Sandbox('*', function (box) {
// console.log(box);
});
Sandbox(function (box) {
// console.log(box);
});
沙盘模式应该足够灵活,并支持在沙盘的回调函数中再次使用沙盘函数:
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()加入静态属性来存放一些数据。
2. 定义模块
在 介绍Sandbox的实现之前,先看看如何定义模块。在沙盘模式中,全局的构造函数Sandbox是个函数对象,因此可以为它加入一个静态的属性来保存各 个模块,比如modules。modules是Sandbox的成员属性,也是一个对象,它通过内部的键值对来保存模块,键作为模块名,而值是模块的实 现。定义模块的做法是这样的:
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 () {};
};
上面的例子里,我们给modules对象加入了三个模块,分别是dom,event,以及ajax。
3. 实现Sandbox的沙盘构造函数
一个可行的Sandbox构造函数是这样的(实际上,在你的程序里可能需要把Sandbox改成有意义的名字):
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);
}
}
}
// initialize the required modules
for (i = 0; i < modules.length; i += 1) {
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;
}
};
上面实现里的关键内容包括:
  • 检查this是不是Sandbox的实例,如果不是(说明不是用new调用的Sandbox())就再次用new调用Sandbox;
  • 可以用this为构造函数添加属性,也可以通过prototype来添加属性;
  • 需要使用的模块可以通过模块名的数组传入,也可以使用每个参数一个模块名的方式传入,“*”匹配所有支持的模块(实际的使用中可以还需要引入定义所需模块的js文件);
  • 如果所需的模块已经定义了,就初始化它,也就是执行定义模块的函数;
  • Sandbox函数的最后一个参数是个回调函数,它在Sandbox函数的最后被调用,并使用Sandbox创建的对象来执行相应的代码,这些代码就像在一个沙盘中运行一样:它们得到了需要支持的模块,而且与外部代码相隔离。

JavaScript基础对象创建模式之沙盘模式(026)的更多相关文章

  1. JavaScript基础对象创建模式之单体/单例模式(Singleton)

    首先,单例模式是对象的创建模式之一,此外还包括工厂模式.单例模式的三个特点: 1,该类只有一个实例 2,该类自行创建该实例(在该类内部创建自身的实例对象) 3,向整个系统公开这个实例接口 Java中大 ...

  2. JavaScript基础对象创建模式之模块模式(Module Pattern)(025)

    模块模式可以提供软件架构,为不断增长的代码提供组织形式.JavaScript没有提供package的语言表示,但我们可以通过模块模式来分解并组织 代码块,这些黑盒的代码块内的功能可以根据不断变化的软件 ...

  3. JavaScript基础对象创建模式之命名空间(Namespace)模式(022)

    JavaScript中的创建对象的基本方法有字面声明(Object Literal)和构造函数两种,但JavaScript并没有特别的语法来表示如命名空间.模块.包.私有属性.静态属性等等面向对象程序 ...

  4. JavaScript基础对象创建模式之链式调用模式(Chaining Pattern)(029)

    链式调用模式允许一个接一个地调用对象的方法.这种模式不考虑保存函数的返回值,所以整个调用可以在同一行内完成: myobj.method1("hello").method2().me ...

  5. JavaScript基础对象创建模式之静态成员(027)

    在支持“类”的面向对象语言中,静态成员指的是那些所有实例对象共有的类成员.静态成员实际是是“类”的成员,而非“对象”的成员.所以如果 MathUtils类中有个叫 max()的静态成员方法,那么调用这 ...

  6. JavaScript基础对象创建模式之私有属性和方法(024)

    JavaScript没有特殊的语法来表示对象的私有属性和方法,默认的情况下,所有的属性和方法都是公有的.如下面用字面声明的对象: var myobj = { myprop: 1, getProp: f ...

  7. JavaScript基础对象创建模式之声明依赖模式(023)

    运用了命名空间(Namespace)模式后, 就可以使用一些JavaScript库了,比如YAHOO作用YUI2库的全局对象,可以通过 YAHOO.util.Dom 和 YAHOO.util.Even ...

  8. JavaScript基础对象创建模式之对象的常量(028)

    虽然许多编程语言提供了const关键字来支持常量的声明,但JavaScript里没有表示常量的语义.我们可以用全大写的方式来声明变量,表明它实际上是个常量: Math.PI; // 3.1415926 ...

  9. javascript的对象创建模式---命名空间模式

    javascript中对象的概念是很普遍的,对象是是对象,数组是对象,函数也是对象,字符串其实也是对象.常见的对象创建方法有对象字面量.构造函数创建.我们先来看看对象的创建还有哪些更高级的模式. 一. ...

随机推荐

  1. (Java实现) 洛谷 P1691 有重复元素的排列问题

    题目描述 设R={r1,r2,--,rn}是要进行排列的n个元素.其中元素r1,r2,--,rn可能相同.使设计一个算法,列出R的所有不同排列. 给定n以及待排列的n个元素.计算出这n个元素的所有不同 ...

  2. Java实现 蓝桥杯VIP 基础练习 芯片测试

    问题描述 有n(2≤n≤20)块芯片,有好有坏,已知好芯片比坏芯片多. 每个芯片都能用来测试其他芯片.用好芯片测试其他芯片时,能正确给出被测试芯片是好还是坏.而用坏芯片测试其他芯片时,会随机给出好或是 ...

  3. Java实现无向图的欧拉回路判断问题

    1 问题描述 Problem Description 欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路.现给定一个图,问是否存在欧拉回路? Input 测试输入包含若干测试 ...

  4. java实现第四届蓝桥杯带分数

    带分数 题目描述 100 可以表示为带分数的形式:100 = 3 + 69258 / 714 还可以表示为:100 = 82 + 3546 / 197 注意特征:带分数中,数字1~9分别出现且只出现一 ...

  5. OV2640读ID全是FF问题

    最近刚好在Cyclone IV上通过LVDS把一个7寸的屏点亮,赶着热度,淘宝买了OV2640这个摄像头模块,初始化因为用Vrilog比C复杂得多,易调试性不如C,所以使用STM32初始化,模块有F3 ...

  6. mysql基础之-mysql存储引擎概述(八)

    0x01 mysql 存储引擎:存储引擎也通常被称作“表类型” mysql> show engines;   --- 查看当前所有所支持的存储引擎 mysql> show table st ...

  7. Python脚本批量修改服务器密码

    搭建环境 centos 7.4 使用脚本 python 批量修改connect用户的密码 生成密码为随机密码 保存为xls文档   passwd_chang #!/usr/bin/env python ...

  8. 源码分析(4)-ConcurrentHashMap(JDK1.8)

    一.UML类图 ConcurrentHashMap键值不能为null:底层数据结构是数组+链表/红黑二叉树:采用CAS(比较并交换)和synchronized来保证并发安全. CAS文章:https: ...

  9. go语言实现"生产者"和"消费者"的例子

    学习java的多线程的时候最经典的一个例子就是生产者消费者模型的例子,最近在研究go语言协程,发现go提供的sync包中有很多和java类似的锁工具,尝试着用锁工具配合协程实现一个"消费者& ...

  10. Verifying dml pool data

    数据出错 ,硬件变动 解决方案: 1.移除外接设备 2.bios还原