用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 相关文章推荐
JavaScrip单线程引擎工作原理分析
Sep 04 Javascript
通过DOM脚本去设置样式信息
Sep 19 Javascript
js页面滚动时层智能浮动定位实现(jQuery/MooTools)
Aug 23 Javascript
Javascript delete 引用类型对象
Nov 01 Javascript
初识Node.js
Sep 03 Javascript
JavaScript实现模仿桌面窗口的方法
Jul 18 Javascript
JavaScript跨域调用基于JSON的RESTful API
Jul 09 Javascript
jQuery实现的tab标签切换效果示例
Sep 05 Javascript
js实现一个可以兼容PC端和移动端的div拖动效果实例
Dec 09 Javascript
BootStrap整体框架之基础布局组件
Dec 15 Javascript
利用Angular2的Observables实现交互控制的方法
Dec 27 Javascript
微信小程序基础教程之worker线程的使用方法
Jul 15 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
header中Content-Disposition的作用与使用方法
2012/06/13 PHP
PHP中操作ini配置文件的方法
2013/04/25 PHP
PHP检测用户语言的方法
2015/06/15 PHP
phpMyAdmin无法登陆的解决方法
2017/04/27 PHP
PHP实现基于栈的后缀表达式求值功能
2017/11/10 PHP
解决在Laravel 中处理OPTIONS请求的问题
2019/10/11 PHP
Gambit vs CL BO3 第一场 2.13
2021/03/10 DOTA
utf-8编码引起js输出中文乱码的解决办法
2010/06/23 Javascript
浅谈JS中json数据的处理
2016/06/30 Javascript
几种二级联动案例(jQuery\Array\Ajax php)
2016/08/13 Javascript
JS实现仿百度文库评分功能
2017/01/12 Javascript
JS得到当前时间的方法示例
2017/03/24 Javascript
jQuery插件FusionCharts绘制2D柱状图和折线图的组合图效果示例【附demo源码】
2017/04/10 jQuery
JS FormData上传文件的设置方法
2017/07/05 Javascript
js单页hash路由原理与应用实战详解
2017/08/14 Javascript
js 图片转base64的方式(两种)
2018/04/24 Javascript
在vue-cli搭建的项目中增加后台mock接口的方法
2018/04/26 Javascript
[36:19]2018DOTA2亚洲邀请赛 小组赛 A组加赛 Newbee vs LGD
2018/04/03 DOTA
python TCP Socket的粘包和分包的处理详解
2018/02/09 Python
python opencv摄像头的简单应用
2019/06/06 Python
Django框架之登录后自定义跳转页面的实现方法
2019/07/18 Python
Django多数据库的实现过程详解
2019/08/01 Python
Python中and和or如何使用
2020/05/28 Python
施华洛世奇德国官网:SWAROVSKI德国
2017/02/01 全球购物
世界知名接发和假发品牌:Poze Hair
2017/03/08 全球购物
2013年大学生的自我鉴定
2013/10/24 职场文书
绩效工资分配方案
2014/01/18 职场文书
青年教师培训方案
2014/02/06 职场文书
学校地质灾害防治方案
2014/06/10 职场文书
ktv周年庆活动方案
2014/08/18 职场文书
2014离婚协议书范文
2014/09/10 职场文书
优秀班主任材料
2014/12/16 职场文书
销售辞职信范文
2015/03/02 职场文书
安全第一课观后感
2015/06/18 职场文书
中小学教师继续教育心得体会
2016/01/19 职场文书
Element-ui Layout布局(Row和Col组件)的实现
2021/12/06 Vue.js