用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 相关文章推荐
javascript客户端解决方案 缓存提供程序
Jul 14 Javascript
关于include标签导致js路径找不到的问题分析及解决
Jul 09 Javascript
JS中产生20位随机数以0-9为例也可以是a-z A-Z
Aug 01 Javascript
运用jQuery定时器的原理实现banner图片切换
Oct 22 Javascript
JS中捕获console.log()输出的方法
Apr 16 Javascript
AngularJs学习第八篇 过滤器filter创建
Jun 08 Javascript
jQuery增加、删除及修改select option的方法
Aug 19 Javascript
vue实现文件上传功能
Aug 13 Javascript
解决layui前端框架 form表单,table表等内置控件不显示的问题
Aug 19 Javascript
对angularJs中controller控制器scope父子集作用域的实例讲解
Oct 08 Javascript
vue 插件的方法代码详解
Jun 06 Javascript
vue.js路由mode配置之去掉url上默认的#方法
Nov 01 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
咖啡知识 咖啡养豆要养多久 排气又是什么
2021/03/06 新手入门
从零开始学YII2框架(五)快速生成代码工具 Gii 的使用
2014/08/20 PHP
php nginx 实时输出的简单实现方法
2018/01/21 PHP
将input file的选择的文件清空的两种解决方案
2013/10/21 Javascript
js QQ客服悬浮效果实现代码
2014/12/12 Javascript
html的DOM中document对象images集合用法实例
2015/01/21 Javascript
Node.js编写组件的三种实现方式
2016/02/25 Javascript
Radio 单选JS动态添加的选项onchange事件无效的解决方法
2016/12/12 Javascript
基于JS实现仿百度百家主页的轮播图效果
2017/03/06 Javascript
JS判断非空至少输入两个字符的简单实现方法
2017/06/23 Javascript
React-Native使用Mobx实现购物车功能
2017/09/14 Javascript
vue自定义指令directive实例详解
2018/01/17 Javascript
npm全局模块卸载及默认安装目录修改方法
2018/05/15 Javascript
深入理解Vue.js轻量高效的前端组件化方案
2018/12/10 Javascript
[02:32]DOTA2英雄基础教程 祸乱之源
2013/12/23 DOTA
[01:10:02]IG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
Python实现列表转换成字典数据结构的方法
2016/03/11 Python
Python3.6正式版新特性预览
2016/12/15 Python
Django内容增加富文本功能的实例
2017/10/17 Python
通过PYTHON来实现图像分割详解
2019/06/26 Python
Python socket模块方法实现详解
2019/11/05 Python
django 多数据库及分库实现方式
2020/04/01 Python
Jupyter Notebook添加代码自动补全功能的实现
2021/01/07 Python
100%羊绒:NakedCashmere
2020/08/26 全球购物
大学英语演讲稿范文
2014/04/24 职场文书
计算机专业求职信
2014/06/02 职场文书
同学聚会策划方案
2014/06/06 职场文书
超市优秀员工获奖感言
2014/08/15 职场文书
党员干部群众路线个人整改措施
2014/09/18 职场文书
2014年幼师工作总结
2014/11/22 职场文书
年终工作总结范文2014
2014/11/27 职场文书
忠犬八公的故事观后感
2015/06/05 职场文书
教师远程研修感悟
2015/11/18 职场文书
2016年员工年度考核评语
2015/12/02 职场文书
python 模拟在天空中放风筝的示例代码
2021/04/21 Python
Python 统计序列中元素的出现频度
2022/04/26 Python