JavaScript 组件之旅(二):编码实现和算法
作者:太伯 来源:alipay UED 发布时间:2009-10-09 14:24:00
目录:
话说上期我们讨论了队列管理组件的设计,并且给它取了个响亮而独特的名字:Smart Queue. 这次,我们要将之前的设计成果付诸实践,用代码来实现它。
首先,我们要考虑一下它的源文件布局,也就是决定代码如何拆分到独立的文件中去。为什么要这么做呢?还记得上期结尾处我提到这个组件会使用“外部代码”吗?为了区分代码的用途,决定将代码至少分成两部分:外部代码文件和 Smart Queue 文件。
区分用途只是其一,其二,分散到独立文件有利于代码的维护。试想,以后的某一天你决定要在现有的队列管理基本功能之上,添加一些新的扩展功能,或是把它包装成某个实现特定任务的组件,而又希望保持现有功能(内部实现)和调用方式(对外接口)不变,那么将新的代码写到单独的文件是最好的选择。
嗯,下期会重点谈谈文件布局的话题,现在要开始切入正题了。第一步,当然是要为组件创建自己的命名空间,组件所有的代码都将限制在这个顶层命名空间内:
var SmartQueue = window.SmartQueue || {};
SmartQueue.version = '0.1';
初始化的时候,如果碰到命名空间冲突就把它拉过来用。通常这个冲突是由重复引用组件代码导致的,因此“拉过来用”会将对象以同样的实现重写一次;最坏的情况下,如果碰巧页面上另一个对象也叫 SmartQueue, 那不好意思了,我会覆盖你的实现——如果没有进一步的命名冲突,基本上两个组件可以相安无事地运行。同时顺便给它一个版本号。
接着,按三个优先级为 SmartQueue 创建三个队列:
var Q = SmartQueue.Queue = [[], [], []];
每个都是空数组,因为还没有任务加进去嘛。又顺便给它建个“快捷方式”,后面要访问数组直接写 Q[n] 就可以啦。
接下来,我们的主角 Task 隆重登场——怎么 new 一个 Task, 定义在这里:
var T = SmartQueue.Task = function(fn, level, name, dependencies) {
if(typeof fn !== FUNCTION) {
throw new Error('Invalid argument type: fn.');
}
this.fn = fn;
this.level = _validateLevel(level) ? level : LEVEL_NORMAL;
// detect type of name
this.name = typeof name === STRING && name ? name : 't' + _id++;
// dependencies could be retrieved as an 'Object', so use instanceof instead.
this.dependencies = dependencies instanceof Array ? dependencies : [];
};
里面的具体细节就不说了,有必要的注释,一般我们的代码也能做到自我描述,后面代码也是这样。这里告诉客户(使用者):你想新建一个 SmartQueue.Task 实例,就要至少传一个参数给这个构造函数(后 3 个都可以省略进行缺省处理),否则抛出异常伺候。
但是这还不够,有时候,客户希望从已有 Task 克隆一个新实例,或是从一个“残废体”(具有部分 Task 属性的对象)修复出“健康体”(真正的 Task 对象实例),通过上面的构造方式就有点不爽了——客户得这样写:
var task1 = new SmartQueue.Task(obj.fn, 1, '', obj.dependencies);
我很懒,我只想传 fn 和 dependencies 两个属性,不想做额外的事情。好吧,我们来重构一下构造函数:
var _setupTask = function(fn, level, name, dependencies) {
if(typeof fn !== FUNCTION) {
throw new Error('Invalid argument type: fn.');
}
this.fn = fn;
this.level = _validateLevel(level) ? level : LEVEL_NORMAL;
// detect type of name
this.name = typeof name === STRING && name ? name : 't' + _id++;
// dependencies could be retrieved as an 'Object', so use instanceof instead.
this.dependencies = dependencies instanceof Array ? dependencies : [];
};
var T = SmartQueue.Task = function(task) {
if(arguments.length > 1) {
_setupTask.apply(this, arguments);
} else {
_setupTask.call(this, task.fn, task.level, task.name, task.dependencies);
}
// init context/scope and data for the task.
this.context = task.context || window;
this.data = task.data || {};
};
如此一来,原来的构造方式可以继续工作,而上面的懒人可以这样传入一个“残废体”:
var task1 = new SmartQueue.Task({fn: obj.fn, dependencies: obj.dependencies});
当构造函数收到多个参数时,按之前的方案等同处理;否则,视唯一的参数为 Task 对象或“残废体”。这里通过 JavaScript 中的 apply
/call
方法将新实例传给重构出来的 _setupTask
方法,作为该方法的上下文 (context, 也有称为 scope), apply
/call
是 JavaScript 在方法之间传递上下文的法宝,要用心体会哦。同时,允许用户定义 task.fn
在执行时的上下文,并将自定义的数据传递给执行中的 fn.
猜你喜欢
- 赠送QQ秀流程是QQ秀商城关键流程之一,占了收入最直接的一部分。它的优化是后续商城流程优化的重要参考。OK,现在就用TA做例子,分享一下流程
- numpy.ndarray添加元素平常使用的比较多的是list,在list后面添加元素直接是data_list = []data_list.
- 在读取中文的情况下,通常会遇到一些编码的问题,但是首先需要了解目前的编码方式是什么,然后再用decode或者encode去编码和解码,下面是
- 本文实例讲述了Python存取XML的常见方法。分享给大家供大家参考,具体如下:目前而言,Python 3.2存取XML有以下四种方法:1.
- 目录1,刚开始(可能会很low)2.单行消失3.优化后的单行消失总结1,刚开始(可能会很low)import timescale=10pri
- 虽然说表单验证在客户端使用javascript来验证已经可以了,但是我们为了防止访客绕过客户端验证也为了数据安全最好还是在服务器端加上必要的
- 很多时候,查看一个文件夹下的每个文件大小可以轻易的做到,因为文件后面就是文件尺寸,但是如果需要查看一个文件夹下面所有的文件夹对应的尺寸,就发
- pytorch做标准化利用transforms.Normalize(mean_vals, std_vals),其中常用数据集的均值方差有:i
- 一.使用库说明Golang中连接kafka可以使用第三方库:github.com/Shopify/sarama二.Kafka Produce
- Python continue语句返回while循环的开始。Continue语句拒绝在该循环的当前迭代中的其余语句执行并移动控制
- 编码格式常见的编码格式:Python的解释器使用的是Unicode(内存).py文件在磁盘上使用UTF-8(外存)更改编码格式一般形式为在程
- 由于本人经常装系统,每次装完系统之后都要重新安装一些软件,安装软件的时候又要上网查找安装的教程,比较麻烦,所以自己整理了MySQL5.7.2
- 一、打开/关闭文件1、对文件操作时首先要打开文件,打开文件用 fopen()函数,语法是:fopen(filename,mode,inclu
- 简单定义图轴:import numpy as npimport matplotlib.pyplot as plt创建一个简单的matplot
- 之前上传图片都是直接将图片转化为io流传给服务器,没有用框架传图片。最近做项目,打算换个方法上传图片。Android发展到现在,Okhttp
- 我们怎样才能了解用户需求呢?大家都知道可用性测试、调查问卷之类与用户进行沟通的途径,这些方法各有各的利弊,如果逐一分析的话,恐怕至少要分成三
- 模版基本介绍模板是一个文本,用于分离文档的表现形式和内容。 模板定义了占位符以及各种用于规范文档该如何显示的各部分基本逻辑(模板标签)。 模
- 一、CrawlSpider类介绍1.1 引入使用scrapy框架进行全站数据爬取可以基于Spider类,也可以使用接下来用到的CrawlSp
- 一道Python课作业题,大致如下:编写一个类:该类Building应具有以下方法:●一个构造函数,它根本不接受任何参数(除了通常的`sel
- 本文实例为大家分享了使用RNN进行文本分类,python代码实现,供大家参考,具体内容如下1、本博客项目由来是oxford 的nlp 深度学