JSX 的前世

ECMA-357

React 的主要創新在於 Virtual DOM,而伴隨著 Virtual DOM 而來的,就是 Virtual DOM 的操作,由於 JavaScript 語言限制的關係,要產生一個簡單的<div>標籤就要寫成:

var divNode = React.DOM.div({attr1:"value"});

如果還要加上子元素,像是一個 list:

<ol>
  <li>Item A</li>
  <li>Item B</li>
  <li>Item C</li>
  <li>Item D</li>
</ol>

就要寫成:

var listNode = React.DOM.div({},
  React.DOM.li({}, "Item A"),
  React.DOM.li({}, "Item B"),
  React.DOM.li({}, "Item C"),
  React.DOM.li({}, "Item D")
);

雖然比起純 DOM 的語法要簡單很多了,不過其實類似這種寫法來快速產生文件樹節點的 library 已經早就有了,像是 Moomlhyperscript(thanks WM),如果 React 當初就直接這樣子推出,大家會想嘗試的意願應該會低很多,Facebook 的工程師應該也知道這樣和直接寫 DOM 或是其他 library 的感覺差異不大,所以他們解決的方法就是建立了一個新的 syntax,看起來就像是讓 DOM 變成像是原生的資料型態一樣,也就是現在的 JSX syntax,然後當然要讓這種語法可以在瀏覽器執行,所以官方有提供了 transpiler,不過其實這個把 XML DOM 當成 JS 語言中的原生資料型態的想法不是第一次出現了,早在好幾年前,就有一個 ECMA-357,又稱為 E4X 的標準是在做這件事的,全名則是 ECMAScript for XML,早期的 Mozilla SpiderMonkey 是有支援的,約是在 2006 年的 JavaScript 1.6 中推出,不過到 Firefox 21 的時候已經完全移除了,所以現在基本上是已經無法體會到這套 JS 擴充的語法,不過其實這套語法還蠻不錯的,有類似 template string 的寫法:

var doc = <{h}><body>{text}</body></{h}>;

React 則因為同時導入了 immutable 的概念,所以其 Virtual DOM 設計上只有產生文件樹結構的部分,沒有刪除修改,相較於 JSX 只有建置(create)的語法,E4X 則是有更完整的 CRUD 操作(就像是操作 JS 資料一樣),另外還多了用來尋找目標節點的 selector syntax:

languages.lang[1]
person..*
people.person.(name == "Joe").age

而且目標對像是 XML,所以對於 namespace 的處理也都有,整體而言算是很完整的 XML 操作方案,使用起來也比 DOM 簡潔很多,可惜後來被放棄,我推測大概幾個原因:

  1. 使用 XML 的應用越來越少
  2. 實做 E4X 會增加 JS 引擎的複雜度
  3. 相較於 DOM 不依存於單一程式語言,E4X 則是 JS extension
  4. 用 E4X 產生的節點不是 DOM 物件,不直接相容

沒想到後來會在 Facebook 的手上,把這個概念單存的套用在 HTML 文件樹之上而重生。