【譯】V8 團隊眼中的 ES6、ES7及未來

原文鏈接:http://v8project.blogspot.com/2016/04/es6-es7-and-beyond.html

推薦國內最好的在線翻譯平臺 眾成翻譯

V8團隊致力于讓 JavaScript 演變成一門表達能力強,定義明確,更容易開發高效、安全、正確的Web應用的編程語言。2015年6月,ES6規范 經由TC39標準委員會的批準,成為 JavaScript 語言版本的一次最大的升級。這次升級為 JavaScript 帶來了許多新特新包括 classes, arrow functions, promises, iterators / generators, proxies, well-known symbols 和一些額外的語法糖。TC39標準委員會也加快了新規范定稿的節奏并于2016年2月發布了ES7的草案,該草案預計將在今年夏天定稿。由于發布周期較短,與ES6相比,ES7并沒有增加太多的新特性,比較引人注意的是它增加了 乘方運算符 和 Array.prototype.includes( )。

ES6,ES7

今天,JavaScript 引擎發展到了一個重要的里程碑:V8 支持了 ES6 和 ES7。你可以通過安裝 Chrome Canary 版本(Chrome 金絲雀版,一個比 Dev 還要更新得更快的版本 ---- 譯者注)使用這些新的語言特性,而這些新特性將在 Chrome 52 正式版中默認支持。

由于規范在不斷演變,Web兼容性、實現一致性等各種復雜,使得決定什么特性在哪個 JavaScript 引擎版本被充分支持成為個難題。接下來我們討論為什么引擎考慮對規范的支持相比于升級版本號要復雜得多,為什么尾調用優化到目前為止依然在討論中,以及還有什么附加工作還在進行中。

演變的規范

當TC39標準委員會決定加快升級 JavaScript 的腳步后,JavaScript 語言的最新版本成為了非正式的草稿版本。雖然 ECMAScript 規范以年為周期提出草稿和正式發布,但 V8 引擎不僅僅實現了最新的正式版本(例如:ES6),還包括一些已經幾乎成為標準,不會再有大的變化,實現足夠安全(以后應該不會再大改)的特性(例如:乘方運算符和Array.prototype.includes()從ES7草稿中實現)。V8引擎遵循的一個基本的原則是,瀏覽器中的語言特性實現要遵守現有規范,或者至少是即將成為的規范。事實上,實現一個正式版本的語言規范的過程涵蓋了對一些特性的修正和完善,這些修正許多會被包含到下一版本的 ECMAScript 規范中去。

如圖:當前實現的特性中包含部分還在進展中的規范

舉一個現實的例子,如果我們要實現 ES6 規范里規定的正則表達式的粘滯匹配,V8引擎團隊發現這個新規范一旦支持將使得許多之前正常的網站出現錯誤(比如那些使用了XRegExp這個流行的npm庫的網站全不好使了)。由于保證兼容性是web的重要考量,V8和Safari JavaScriptCore團隊的工程師們提出了一個修正案給正則表達式規范來防止之前的網站出錯,這個修正得到TC39標準委員會的認同。這個修正案預計在ES8中由TC39標準委員會正式提出,但它已然成為ECMAScript語言的一部分,V8引擎已經實現了它。

語言規范的不斷細化意味著每一個版本(包括仍在評估中的草案)不斷修正和完善之前的版本,引擎的升級表面上在不斷支持 ES6 和 ES7 特性,事實上底下的工作非常復雜。不考慮實際情況僅根據語言規范一刀切是不可能的,可能對 V8 引擎最恰當的描述是,V8 的實現遵循"盡可能貼近未來ECMAScript標準"這一原則。

衡量一致性

有許多方法可以衡量JavaScript引擎對ECMAScript標準的兼容性,從而評估實現該規范有多復雜。V8團隊,以及其他瀏覽器廠商,使用 test262 測試用例作為持續保持與未來 ECMAScript 標準草案相一致的金科玉律。這組測試用例隨著規范持續升級,并提供超過 16000 個單元測試,用來充分測試所有的語言特性,涵蓋了邊界條件。當前 V8 引擎通過了大約 98% 的測試用例,剩下的 2% 之所以沒通過是因為有少數邊界情況以及有部分還沒有準備好支持的特性。

由于test262用例數目非常龐大,瀏覽結果成本也很高,所以還可以考慮其他可選方案,例如檢查Kangax compatibility table。kangax 整理的兼容性速查表能夠非常方便地查看一個特性是否被特定瀏覽器引擎實現(比如箭頭函數),但是Kangax表沒有充分測試所有的邊界條件。目前為止,Chrome Canary 版本在Kangax表上支持了 98% 的 ES6 規范和 100% 的Kangax表列出的 ES7 規范(例如,在表上在ESnext tab頁中標記為"2016特性"和"2016雜項"的部分)。

Kangax ES6兼容表剩余的2%測試是關于尾調用優化,這個特性其實在V8引擎中已經實現了,但是特意在 Chrome Canary 版本中關閉了,具體關閉這個特性的原因和開發體驗有關,下面會詳細說。如果想要把這個特性加上,可以在設置里面把"實驗的JavaScript特性"選項開啟,這樣就可以強制打開這個特性,那樣 Canary 就完全支持Kangax表上的ES6規范了。

尾調用優化

尾調用優化已經被實現但是沒有在特性中默認支持的理由目前正在TC39標準委員會中討論。ES6規范要求在嚴格模式下,函數尾調用不會出現堆棧溢出。這對某些編程范式是非常有用的(例如函數式編程----譯者注),然而現在的實現方式有兩個問題。首先,由于引擎消除尾遞歸是隱式的,函數是否符合尾調用而被消除了尾遞歸很難被程序員自己辨別。這意味著開發者可能很難發現一些死的遞歸,如果它們恰好出現在末尾,因為這些遞歸的堆棧將不再溢出。其次,尾調用優化要求除掉尾調用執行時的調用堆棧,這將導致執行流中的堆棧信息丟失。這又進一步導致了兩個后果:

  1. 這使得調試過程中信息更加難懂,因為堆棧不連續。
  2. Error.prototype.stack 包含的執行流信息不完整可能會導致依賴于這些錯誤信息的收集分析用戶端信息的一些遙測軟件出錯。

實現一個影子堆棧可以改善堆棧信息缺失問題,但是V8引擎和開發者工具團隊還是認為當堆棧信息在調試過程中是完全確定的,并始終符合實際虛擬機堆棧的真實狀態時,調試是最容易,最可靠和最準確的。何況,影子堆棧功能如果默認開啟,會帶來很大的性能開銷。

基于以上原因,V8團隊強烈建議用特殊的語法來指定尾遞歸優化。TC39標準委員會有一個還沒有結論的提案叫做從語法上指定尾部調行為,這個提案由來自 Mozilla 和微軟的委員提出。我們已經準備好了ES6的尾遞歸優化實現,我們也開始實現基于這一提案的尾調用優化語法。我們計劃在下一次TC39會議中解決這一問題,從而決定究竟默認支持隱式尾調用優化還是顯示使用尾調用優化語法。你可以測試每一種實現,通過 V8 啟動參數 --harmony-tailcalls 和 --harmony-explicit-tailcalls。

模塊化

ES6中最激動人心的承諾是 JavaScript 模塊將支持通過名字空間來組織和區分不同的子系統。ES6 import 規范 和 export 規范 聲明了模塊,但是并沒有說明在一個JavaScript程序中該如何加載模塊。在瀏覽器中,最新的模塊加載行為是通過新標簽來指定。盡管還需要額外的標準化工作來支持高級的動態模塊加載API,Chromium已經開始著手支持模塊化的script標簽了。你可以在 launch bug 關注我們的實現工作,在 whatwg/loader 倉庫了解更多關于實驗的模塊加載API的具體思路。

ESnext 未來

可以預見在將來 ECMAScript 升級會變得更頻繁而細碎。V8 團隊已經開始實現更新的特性比如 async /await 關鍵字, Object.values( ) / Object.entries( ), String.prototype.padStart( ) /String.prototype.padEnd( ) 以及 RegExp lookbehind 等等,同時我們也經常檢查ESnext實現進展和針對現有的ES6和ES7做性能優化。

我們力爭繼續推動 JavaScript 的演變,以及在盡早實現新特性和保持現有Web兼容和穩定性之間力求平衡,向TC39標準委員會提出設計問題和實現反饋。我們期待著看這些新特性能為開發者們帶來不同尋常的美妙體驗。


所屬標簽

無標簽

25选5玩法中奖