用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 相关文章推荐
dess中一个简单的多路委托的实现
Jul 20 Javascript
20个非常棒的 jQuery 幻灯片插件和教程分享
Aug 23 Javascript
JS图片自动轮换效果实现思路附截图
Apr 30 Javascript
javascript获取隐藏元素(display:none)的高度和宽度的方法
Jun 06 Javascript
Javascript基于对象三大特性(封装性、继承性、多态性)
Jan 04 Javascript
JQuery手速测试小游戏实现思路详解
Sep 20 Javascript
jQury Ajax使用Token验证身份实例代码
Sep 22 Javascript
Angular实现下拉框模糊查询功能示例
Jan 03 Javascript
JavaScript使用小插件实现倒计时的方法讲解
Mar 11 Javascript
jquery实现简单每周轮换的日历
Sep 10 jQuery
axios解决高并发的方法:axios.all()与axios.spread()的操作
Nov 09 Javascript
如何在现代JavaScript中编写异步任务
Jan 31 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在window iis的莫名问题的测试方法
2013/05/14 PHP
php ci框架验证码实例分析
2013/06/26 PHP
php设计模式之单例、多例设计模式的应用分析
2013/06/30 PHP
PHP抓取淘宝商品的用户晒单评论+图片+搜索商品列表实例
2016/04/14 PHP
静态页面下用javascript操作ACCESS数据库(读增改删)的代码
2007/05/14 Javascript
使用jquery自定义鼠标样式满足个性需求
2013/11/05 Javascript
js中document.write的那点事
2014/12/12 Javascript
js生成随机数的方法实例
2015/10/16 Javascript
JS验证邮件地址格式方法小结
2015/12/01 Javascript
12个非常实用的JavaScript小技巧【推荐】
2016/05/18 Javascript
Knockoutjs 学习系列(一)ko初体验
2016/06/07 Javascript
浅谈jQuery animate easing的具体使用方法(推荐)
2016/06/17 Javascript
BootStrap中关于Select下拉框选择触发事件及扩展
2016/11/22 Javascript
vue动态改变背景图片demo分享
2018/09/13 Javascript
在element-ui的select下拉框加上滚动加载
2019/04/18 Javascript
基于vue的tab-list类目切换商品列表组件的示例代码
2020/02/14 Javascript
Vant 在vue-cli 4.x中按需加载操作
2020/11/05 Javascript
python端口扫描系统实现方法
2014/11/19 Python
Python实现多线程HTTP下载器示例
2017/02/11 Python
Python cookbook(数据结构与算法)从序列中移除重复项且保持元素间顺序不变的方法
2018/03/13 Python
Python unittest模块用法实例分析
2018/05/25 Python
Python collections中的双向队列deque简单介绍详解
2019/11/04 Python
windows环境中利用celery实现简单任务队列过程解析
2019/11/29 Python
在TensorFlow中屏蔽warning的方式
2020/02/04 Python
10行Python代码实现Web自动化管控的示例代码
2020/08/14 Python
Css3新特性应用之形状总结
2016/12/08 HTML / CSS
基督教卡片、励志礼品、家居装饰等:DaySpring
2018/10/12 全球购物
惠普香港官方商店:HP香港
2019/04/30 全球购物
Spotahome意大利:公寓和房间出租
2020/02/21 全球购物
初一科学教学反思
2014/01/27 职场文书
运动会通讯稿100字
2014/01/31 职场文书
财务学生的职业生涯发展
2014/02/11 职场文书
2015年社区宣传工作总结
2015/05/20 职场文书
家庭贫困证明
2015/06/16 职场文书
比较node.js和Deno
2021/04/27 Javascript
python中24小时制转换为12小时制的方法
2021/06/18 Python