用JavaScript对JSON进行模式匹配 (Part 2 - 实现)


Posted in Javascript onJuly 17, 2010

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 的健壮性。
Javascript 相关文章推荐
在chrome中window.onload事件的一些问题
Mar 01 Javascript
点击弹出层效果&amp;弹出窗口后网页背景变暗效果的实现代码
Feb 10 Javascript
Jquery设置attr的disabled属性控制某行显示或者隐藏
Sep 25 Javascript
javascript实现网页背景烟花效果的方法
Aug 06 Javascript
Bootstrap树形控件使用方法详解
Jan 27 Javascript
JavaScript中ES6 Babel正确安装过程
Jul 18 Javascript
浅述Javascript的外部对象
Dec 07 Javascript
js实现短信发送倒计时功能(正则验证)
Feb 10 Javascript
Vue实现可移动水平时间轴
Jun 29 Javascript
js实现简易点击切换显示或隐藏
Nov 29 Javascript
vue中watch的用法汇总
Dec 28 Vue.js
用JS写一个发布订阅模式
Nov 07 Javascript
用JavaScript对JSON进行模式匹配(Part 1-设计)
Jul 17 #Javascript
关于flash遮盖div浮动层的解决方法
Jul 17 #Javascript
JQUERY获取form表单值的代码
Jul 17 #Javascript
jQuery+ajax实现顶一下,踩一下效果
Jul 17 #Javascript
flexigrid 类似ext grid的JS表格代码
Jul 17 #Javascript
基于JQuery的Pager分页器实现代码
Jul 17 #Javascript
基于jQuery的Spin Button自定义文本框数值自增或自减
Jul 17 #Javascript
You might like
php合并数组array_merge函数运算符加号与的区别
2008/10/31 PHP
php 异常处理实现代码
2009/03/10 PHP
IIS6+PHP5+MySQL5+Zend Optimizer+phpMyAdmin安装配置图文教程 2009年
2009/06/08 PHP
centos 5.6 升级php到5.3的方法
2011/05/14 PHP
PHP5.2中PDO的简单使用方法
2016/03/25 PHP
PHP+fiddler抓包采集微信文章阅读数点赞数的思路详解
2019/12/20 PHP
关于javascript event flow 的一个bug详解
2013/09/17 Javascript
javascript转换日期字符串为Date日期对象的方法
2015/02/13 Javascript
JS实现超炫网页烟花动画效果的方法
2015/03/02 Javascript
JS实现为表格动态添加标题的方法
2015/03/31 Javascript
浅谈JavaScript正则表达式分组匹配
2015/04/10 Javascript
JS实现点击事件统计的简单实例
2016/07/10 Javascript
AngularJS入门教程之更多模板详解
2016/08/19 Javascript
详解Angular5 服务端渲染实战
2018/01/04 Javascript
node使用mysql获取数据库数据中文乱码问题的解决
2019/12/02 Javascript
文章或博客自动生成章节目录索引(支持三级)的实现代码
2020/05/10 Javascript
bootstrap实现tab选项卡切换
2020/08/09 Javascript
[01:18]DOTA2超级联赛专访hanci ForLove淘汰感言曝光
2013/06/04 DOTA
python获取豆瓣电影简介代码分享
2014/01/16 Python
python通过百度地图API获取某地址的经纬度详解
2018/01/28 Python
Python列表如何更新值
2020/05/27 Python
matplotlib绘制正余弦曲线图的实现
2021/02/22 Python
HTML5 drag和drop具体使用详解
2021/01/18 HTML / CSS
机电一体化毕业生求职信
2013/11/02 职场文书
电子信息专业自荐书
2014/02/04 职场文书
银行服务感言
2014/03/01 职场文书
法律进企业活动方案
2014/03/04 职场文书
公司委托书格式范文
2014/04/04 职场文书
教师个人自我评价范文
2014/04/13 职场文书
优质服务活动实施方案
2014/05/02 职场文书
市场调查策划方案
2014/06/10 职场文书
毕业生工作求职信
2014/06/30 职场文书
见义勇为事迹材料
2014/12/24 职场文书
高中物理教学反思
2016/02/19 职场文书
alibaba seata服务端具体实现
2022/02/24 Java/Android
Win11 25163.1010更新补丁KB5016904推送,测试服务验证管道(附更新修复汇总)
2022/07/23 数码科技