用 JavaScript 对 JSON 进行模式匹配 (Part 2 - 实现)
2010-07-15 14:58
507 查看
在上一篇文章里,我们完成了
这段代码的逻辑很清晰,关键就在于
这样我们只要把
一个比较难的函数是
其他运算符会简单一些,在此我仅仅给出提示,大家可以根据自己的实际需求这些运算符的子集或超集:
写好了吗?不太确信自己写得是否正确?这是我们下一篇文章要讨论的内容,让我们先加上一个默认运算符。
为什么需要一个默认运算符?这其实只是一个快捷方式。在大多数时候,我们需要的都是
显然,第一个更直观一些。因此,我们需要一个默认运算符,当运算符字符串就是
为什么需要考虑
写运算符,最需要的是严谨性。因为
Dispatcher类的接口设计,现在我们就来考虑一下如何实现这个类。
Notify & Capture
要实现notify和
capture就太容易了,我们只需要把
capture传入的 handler 都保存下来,然后在
notify里面找到匹配的 handler 就可以了。
var filterHandlerBundles = []; Dispatch.capture = function(pattern, handler) { var filter = createFilter(pattern); filterHandlerBundles.push({ "filter": filter, "handler": handler }); }; Dispatcher.notify = function(json) { for (var i = 0; i < filterHandlerBundles.length; i++) { if (filterHandlerBundles[i].filter.apply(this, arguments)) { filterHandlerBundles[i].handler(json); } } };
这段代码的逻辑很清晰,关键就在于
createFilter的部分。这个函数负责把一个描述模式的 JSON 转换为一个判断 JSON 是否匹配的函数。
Operators
我们设计了不少的运算法,如何实现他们呢?记住,我们不要 switch case 。因此,我们使用一个关联数组来保存运算符与实现之间的映射关系好了 。var operators = {}; operators["lt"] = function(testValue, value) { return arguments.length == 2 && value < testValue; }; operators["lte"] = function(testValue, value) { return arguments.length == 2 && value <= testValue; }; operators["gt"] = function(testValue, value) { return arguments.length == 2 && value > testValue; }; operators["gte"] = function(testValue, value) { return arguments.length == 2 && value >= testValue; };
这样我们只要把
"$"后面的运算符抽取出来,就可以立即找到对应的判断函数了。上面4个是比较运算符,由于实现比较容易,所以放在这里做例子。
一个比较难的函数是
eq,因为它需要根据数据类型来选择具体的判断方式。对于 String 、 Number 、 Boolean ,
eq的含义就是
==;对于 Array ,
eq的含义就是里面的每一个元素都
eq,而且顺序一致;对于 Object ,
eq的含义是每一个子条件都符合,因此我们需要将每一个子条件的运算符字符串提取出来,然后调用对应的运算符。具体可以参考完整代码。
其他运算符会简单一些,在此我仅仅给出提示,大家可以根据自己的实际需求这些运算符的子集或超集:
in- 遍历数组,看能否找到至少一个
eq的。
all- 遍历数组,看是否每一个都存在
eq的。
ex- 如果有传入值,则子元素存在。
re- 用正则表达式判断字符串是否匹配。
ld- 直接调用函数进行判断。
写好了吗?不太确信自己写得是否正确?这是我们下一篇文章要讨论的内容,让我们先加上一个默认运算符。
operators[""] = function(testValue, value) { if (testValue instanceof Array) { return operators["in"].apply(this, arguments); } else if (testValue instanceof RegExp) { return operators["re"].apply(this, arguments); } else if (testValue instanceof Function) { return operators["ld"].apply(this, arguments); } else { return operators["eq"].apply(this, arguments); } };
为什么需要一个默认运算符?这其实只是一个快捷方式。在大多数时候,我们需要的都是
eq运算,如果每一处都要把运算符写上,代码将变得很复杂,也不美观。对比一下两个 JSON ,你觉得哪个更自然?
Dispatcher.capture({ "status": 200, "command": "message" }, function(json) { /* display message */ }); Dispatcher.capture({ "status$eq": 200, "command$eq": "message" }, function(json) { /* display message */ });
显然,第一个更直观一些。因此,我们需要一个默认运算符,当运算符字符串就是
""时,就通过默认运算符选择一个运算符。
Pattern to Filter
最后,我们需要把operators和
createFilter接上。这部分工作其实也不难,只要调用默认运算符就可以了。
var createFilter = function(condition) { return function(json) { if (arguments.length > 0) { return operators[""](condition, json); } else { return operators[""](condition); } }; };
为什么需要考虑
json参数没有传入的情况?下次文章再告诉你。不这样做也可以,只是有些很细小的问题而已。
写运算符,最需要的是严谨性。因为
Dispatcher是一个封装好的组件,运算符一点点的不严谨,都会把缺陷埋藏得很深,很难找出来。因此,下一篇文章我们要讨论的是单元测试,通过单元测试我们可以大大提高
Dispatcher的健壮性。如果你对此感兴趣,记得到 Twitter 上来关注我: @CatChen
相关文章推荐
- 用JavaScript对JSON进行模式匹配 (Part 2 - 实现)
- 用JavaScript对JSON进行模式匹配 (Part 2 - 实现)
- 用JavaScript对JSON进行模式匹配(Part 1-设计)
- 用JavaScript对JSON进行模式匹配(Part 1-设计)
- 用 JavaScript 对 JSON 进行模式匹配 (Part 1 - 设计)
- 你知道的,javascript语言的执行环境是"单线程模式",这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行,因此很多时候需要进行“异步模式”,请列举js异步编程的方法。
- 基于JavaScript实现Json数据根据某个字段(json中的某个属性)进行排序
- 模式匹配算法以及KMP的javascript实现
- 基于JavaScript实现Json数据根据某个字段进行排序
- JavaScript 通过模式匹配实现重载
- JavaScript 通过模式匹配实现重载
- 基于JavaScript实现Json数据根据某个字段进行排序
- c#与JavaScript实现对用户名、密码进行RSA非对称加密
- Ajax中数据传递的另一种模式 javascript Object Notation思想(JSON)
- ac自动机实现多模式匹配
- javascript前台生成json,后台进行解析
- 实现JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制
- python2.7通过字典实现java的switch-case模式匹配(代码有注释)
- javascript实现全局匹配并替换的方法
- JavaScript对JSON数据进行排序