jQuery is DSL (Part 2 - jQuery)

作者: Cat Chen  來源: 博客園  發布時間: 2009-08-17 09:57  閱讀: 1672 次  推薦: 0   原文鏈接   [收藏]  

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代碼的含義:

  • 遍歷
    • 中的每一個

    • (這看起來是個聯系人列表)
      • 對于里面的
        • 綁定click事件,操作是顯示/隱藏class="more"兄弟節點
          (這是估計聯系人姓名,點擊后切換詳細信息的顯示/隱藏)
      • 對于里面的
        • 綁定click事件,操作是把class="item"父節點刪除
          (這應該是用來刪除聯系人的)
      • 對于里面的
        • 隱藏這個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的性價比將會是很高的。你需要做的僅僅是為這個簡單的語言模型實現一個簡單的解釋器,接著你就可以享受貼近人類思維模式的接口了。

     

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()