zoukankan      html  css  js  c++  java
  • jQuery is DSL (Part 2 jQuery)

    jQuery的Internal DSL形式

    在上一篇文章里面,我们了解到了Internal DSL的具体形式,形如:

    /* Method Chaining */
    computer()
      .processor()
        .cores(2)
        .i386()
      .disk()
        .size(150)
      .disk()
        .size(75)
        .speed(7200)
        .sata()
      .end();

    然后我们在看看一段典型的jQuery代码:

    $("ul#contacts li.item")
      .find("span.name")
        .click(function(e) { $(e.target).siblings(".more").toggle(); })
        .end()
      .find("input.delete")
        .click(function(e) { $(e.target).parents(".item").remove(); })
        .end()
      .find("div.more")
        .hide()
        .end();

    从结构上来说,是不是跟上面那一段Internal DSL的例子很相似?就算我们不看对应的HTML,我们也能猜到这段jQuery代码的含义:

    • 遍历<ul id="contacts">中的每一个<li class="item">
      (这看起来是个联系人列表)
      • 对于里面的<span class="name">
        • 绑定click事件,操作是显示/隐藏class="more"兄弟节点
          (这是估计联系人姓名,点击后切换详细信息的显示/隐藏)
      • 对于里面的<input class="delete">
        • 绑定click事件,操作是把class="item"父节点删除
          (这应该是用来删除联系人的)
      • 对于里面的<div class="more">
        • 隐藏这个div
          (默认隐藏详细信息?)

    从这里我们已经能够看出jQuery的Internal DSL形式带来的好处——编写代码时,让代码更贴近作者的思维模式;阅读代码时,让读者更容易理解代码的含义。不信?我们看看与jQuery拥有相似功能的Prototype是如何实现上述逻辑:

    $$("ul#contacts li.item span.name")
      .invoke("observe", "click",
        function(e) { $(e.target).next(".more").toggle(); });
    $$("ul#contacts li.item input.delete")
      .invoke("observe", "click",
        function(e) { $(e.target).up(".item").remove(); });
    $$("ul#contacts li.item div.more")
      .invoke("hide");

    这是我用Prototype所能写出的最贴近Internal DSL的形式了。(如果你能够写出一个更自然的版本,欢迎分享。)在Prototype里面,能够返回一组元素的操作就只有$$(),并且它只能作用于全局,缺乏jQuery中find()或者filter()的功能,所以这一组描述联系人列表行为的语句无法组合在一起,必须逐一定义每类元素的行为。此外,此例子中每类元素都仅仅指定了一个行为,因此Prototype的invoke()写法看起来还是和jQuery的click()写法很相近的。但如果一类元素拥有多个行为,Prototype的invoke()就不能好像jQuery那样链式调用下去了,必须每一个行为重头写一个$$(),或者把invoke()改成each()加匿名函数。无论是那种做法,都只会降低代码的可读性。

    jQuery的语法分析器

    我们都知道,Internal DSL的实现依赖于对语法分析器的封装,对Internal DSL的调用其实都是对语法分析器的调用,经过语法分析后再构造出对底层API的调用。例如jQuery当中的click(),它依赖于当前的状态,也就是前面$()筛选出来的节点集合,把click()解释为要为这一组节点绑定DOM的click事件,最后再调用DOM API完成任务。在这个例子当中,DOM API相对jQuery API而言就是底层API了。

    jQuery可以说是挑了一个最容易实现的语法模型来做,永远只有一种token,因此永远也只有一种状态,这种状态当然也是永远有效的,你根本不可能给jQuery输入一个当前状态无效的token。jQuery的唯一状态就是一个jQuery对象实例,其本质就是一个元素集合。读入的token可能是各种针对这个元素集合的操作,但它的返回一定还是一个元素集合。这使得jQuery的语法分析器不会进入无效状态,也就无需判断无效状态,因此大大简化了Internal DSL实现中常见的一个难题。

    小结

    通过拿jQuery和Prototype做对比,我们可以发现jQuery用非常低的成本实现了Internal DSL,同时带来了Prototype所没有的明显好处。这可以看作是一个很好的范例——如果你需要描述的业务逻辑能够归纳为简单的语言模式,为此实现一门Internal DSL的性价比将会是很高的。你需要做的仅仅是为这个简单的语言模型实现一个简单的解释器,接着你就可以享受贴近人类思维模式的接口了。

    最后,如果你喜欢我的文章,可以考虑订阅我的博客:

  • 相关阅读:
    Android之ListView中的分割线
    Android 数据存储(XML解析)
    Altium Designer 15 --- Nets Update
    IAR ------ 基本使用
    Altium Designer 15 --- Make LOGO/ICON
    点云数据处理
    Reconstruction(三维重建)文件被修改
    ORB_SLAM2应用实践_ROS小强机器人
    OpenCV4Android安装
    开题报告
  • 原文地址:https://www.cnblogs.com/cathsfz/p/1547361.html
Copyright © 2011-2022 走看看