技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> JavaScript --> 用 JavaScript 对 JSON 进行模式匹配 (Part 2 - 实现)

用 JavaScript 对 JSON 进行模式匹配 (Part 2 - 实现)

浏览:3746次  出处信息

    在上一篇文章里,我们完成了 Dispatcher 类的接口设计,现在我们就来考虑一下如何实现这个类。

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 的健壮性。

    建议继续学习:

    1. JSON和JSONP的区别    (阅读:7756)
    2. XML和JSON    (阅读:6784)
    3. 如何编写一个JSON解析器    (阅读:5479)
    4. 理解JSON:3分钟课程    (阅读:4804)
    5. 用 JavaScript 对 JSON 进行模式匹配 (Part 1 - 设计)    (阅读:4409)
    6. 前端模板引擎    (阅读:3800)
    7. Ajax和WEB服务数据格式:JSON JSONP    (阅读:3575)
    8. [python]定制JSON中的浮点数格式    (阅读:3041)
    9. JSON对象和字符串之间的相互转换    (阅读:2961)
    10. 让Json更懂中文(JSON_UNESCAPED_UNICODE)    (阅读:2865)
    QQ技术交流群:445447336,欢迎加入!
    扫一扫订阅我的微信号:IT技术博客大学习
    © 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

    京ICP备15002552号-1