用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 相关文章推荐
js改变img标签的src属性在IE下没反应的解决方法
Jul 23 Javascript
Nginx上传文件全部缓存解决方案
Aug 17 Javascript
jQuery实现Flash效果上下翻动的中英文导航菜单代码
Sep 22 Javascript
JavaScript判断FileUpload控件上传文件类型
Sep 28 Javascript
Jquery日历插件制作简单日历
Oct 28 Javascript
js与jQuery实现checkbox复选框全选/全不选的方法
Jan 05 Javascript
JavaScript实现简单的拖动效果
Jul 02 Javascript
jQuery旋转插件jqueryrotate用法详解
Oct 13 Javascript
详解vue-router 2.0 常用基础知识点之导航钩子
May 10 Javascript
使用javaScript实现鼠标拖拽事件
Apr 03 Javascript
react同构实践之实现自己的同构模板
Mar 13 Javascript
Vue+elementui 实现复杂表头和动态增加列的二维表格功能
Sep 23 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
全国FM电台频率大全 - 24 贵州省
2020/03/11 无线电
几个实用的PHP内置函数使用指南
2014/11/27 PHP
php获取Google机器人访问足迹的方法
2015/04/15 PHP
PHP永久登录、记住我功能实现方法和安全做法
2015/04/27 PHP
Linux系统递归生成目录中文件的md5的方法
2015/06/29 PHP
php制作简单模版引擎
2016/04/07 PHP
Laravel如何使用Redis共享Session
2018/02/23 PHP
php 可变函数使用小结
2018/06/12 PHP
PHP asXML()函数讲解
2019/02/03 PHP
JS预览图像将本地图片显示到浏览器上
2013/08/25 Javascript
谈谈jQuery Ajax用法详解
2015/11/27 Javascript
JS组件Bootstrap按钮组与下拉按钮详解
2016/05/10 Javascript
玩转JavaScript OOP - 类的实现详解
2016/06/08 Javascript
jquery常用的12个小功能
2016/07/22 Javascript
bootstrap监听滚动实现头部跟随滚动
2016/11/08 Javascript
详解webpack-dev-server的简单使用
2018/04/02 Javascript
jQuery实现的网站banner图片无缝轮播效果完整实例
2019/01/28 jQuery
layer关闭当前窗口页面以及确认取消按钮的方法
2019/09/09 Javascript
[11:42]2018DOTA2国际邀请赛寻真——OG卷土重来
2018/08/17 DOTA
详解Python设计模式编程中观察者模式与策略模式的运用
2016/03/02 Python
Python3.x对JSON的一些操作示例
2017/09/01 Python
Python语言描述KNN算法与Kd树
2017/12/13 Python
pycharm运行出现ImportError:No module named的解决方法
2018/10/13 Python
解决python3 pika之连接断开的问题
2018/12/18 Python
python字符串反转的四种方法详解
2019/12/02 Python
django实现HttpResponse返回json数据为中文
2020/03/27 Python
Auchan Direct波兰:欧尚在线杂货店
2016/10/19 全球购物
宝拉珍选美国官网:Paula’s Choice美国
2018/01/07 全球购物
凯撒娱乐:Caesars Entertainment
2018/02/23 全球购物
美国宠物用品网站:Value Pet Supplies
2018/03/17 全球购物
Linden Leaves官网:新西兰纯净护肤品
2020/12/20 全球购物
C++:局部变量能否和全局变量重名
2014/03/03 面试题
中学教师请假制度
2014/02/03 职场文书
房屋继承公证书
2014/04/10 职场文书
Python 中数组和数字相乘时的注意事项说明
2021/05/10 Python
python3.7.2 tkinter entry框限定输入数字的操作
2021/05/22 Python