用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 相关文章推荐
javawscript 三级菜单的实现原理
Jul 01 Javascript
js 鼠标拖动对象 可让任何div实现拖动效果
Nov 09 Javascript
xss文件页面内容读取(解决)
Nov 28 Javascript
js文本框输入内容智能提示效果
Dec 02 Javascript
使用 stylelint检查CSS_StyleLint
Apr 28 Javascript
浅谈Javascript中的Label语句
Dec 14 Javascript
React.Js添加与删除onScroll事件的方法详解
Nov 03 Javascript
js精确的加减乘除实例
Nov 14 Javascript
判断jQuery是否加载完成,没完成继续判断的解决方法
Dec 06 jQuery
webpack项目使用eslint建立代码规范实现
May 16 Javascript
Vue中函数防抖节流的理解及应用实现
Apr 24 Javascript
基于Cesium绘制抛物弧线
Nov 18 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 用sock技术发送邮件的函数
2007/07/21 PHP
深入了解 register_globals (附register_globals=off 网站打不开的解决方法)
2012/06/27 PHP
学习php设计模式 php实现模板方法模式
2015/12/08 PHP
PHP http请求超时问题解决方案
2020/11/13 PHP
百度 popup.js 完美修正版非常的不错 脚本之家推荐
2009/04/17 Javascript
JQuery 操作select标签实现代码
2010/05/14 Javascript
js函数定时器实现定时读取系统实时连接数
2014/04/30 Javascript
js+HTML5实现canvas多种颜色渐变效果的方法
2015/06/05 Javascript
js实现新浪微博首页效果
2015/10/16 Javascript
深入探讨Vue.js组件和组件通信
2016/09/12 Javascript
JS闭包与延迟求值用法示例
2016/12/22 Javascript
JS数组去重的6种方法完整实例
2018/12/08 Javascript
vue 更改连接后台的api示例
2019/11/11 Javascript
JSONP 的原理、理解 与 实例分析
2020/05/16 Javascript
python判断端口是否打开的实现代码
2013/02/10 Python
Python3编程实现获取阿里云ECS实例及监控的方法
2017/08/18 Python
Python中的defaultdict与__missing__()使用介绍
2018/02/03 Python
python3+PyQt5使用数据库表视图
2018/04/24 Python
使用Windows批处理和WMI设置Python的环境变量方法
2019/08/14 Python
Python图像处理库PIL的ImageFont模块使用介绍
2020/02/26 Python
在python tkinter界面中添加按钮的实例
2020/03/04 Python
python except异常处理之后不退出,解决异常继续执行的实现
2020/04/25 Python
python字符串的index和find的区别详解
2020/06/20 Python
Sasa莎莎海外旗舰店:香港莎莎美妆平台
2018/03/21 全球购物
回馈慈善的设计师太阳镜:DIFF eyewear
2019/10/17 全球购物
Linux管理员面试题 Linux admin interview questions
2016/07/08 面试题
毕业生实习鉴定
2013/12/11 职场文书
新驾驶员个人自我评价
2014/01/03 职场文书
技能比赛获奖感言
2014/02/14 职场文书
文秘求职信范文
2014/04/10 职场文书
2014客服代表实习自我鉴定
2014/09/18 职场文书
教师个人查摆剖析材料
2014/10/14 职场文书
2014年小学少先队工作总结
2014/12/18 职场文书
商场营业员岗位职责
2015/04/14 职场文书
个人收入证明范本
2015/06/12 职场文书
Typescript类型系统FLOW静态检查基本规范
2022/05/25 Javascript