ES7新特性及ECMAScript標準的制定流程

jopen 8年前發布 | 46K 次閱讀 ECMAScript

2015年6正式發布的ES6是ECMAScript的最新版本,它的發布具有里程碑意義,不僅帶來了眾多的新特性, 而且自此將改變ECMAScript的發布策略。本文將會介紹ECMAScript標準的最新制定過程, 并簡要的介紹將會出現在ECMASCript 2016中的主要新特性。

Statement

基礎知識

ES6作為ECMAScript的最新版本,在ES6發布的近6年后才被正式標準化(2009年12月 vs 2015年6月)。 導致這么長跨度的主要原因有兩個:

  • 所有的特性無論先后,都必須等待新的發行版本(release)完全制定完成后才能公布;
  • 有些特性未能完全達成一致,從而造成了整個發行版本的延遲。如果這些特定推遲到下一個發行版本,那么將會耗費更多的時間。

為了避免這種緩慢的發行版本更新策略,從ECMAScript 2016(ES7)開始,版本的發布將會變得更加頻繁, 這也意味著未來每個新的發行版本都會包含盡可能少的特性,而發行周期則縮短為1年,并且每年只發行確保一年期限內能夠完成的所有特性。 為了向你簡要的介紹新的版本發行策略,首先需要介紹的是TC39。

技術委員會39 (Technical Committee 39 - TC39)

TC39 (ECMA技術委員為39)是推動JavaScript發展的委員會。 它的成員是都是企業(主要是瀏覽器廠商)。TC39會 定期的開會 , 會議的主要成員時是成員公司的代表,以及受邀請的專家。 你可以參考網絡上的一個有關TC39會議的 會議紀要 來了解TC39是如何工作。

在本文中,通常我們用“TC39成員”這個術語來指代一個具體的人,他是由TC39成員公司所委派的會議代表。 有一點值得注意的是,TC39必須達成全員一致的協議:決策只有被所有的成員單位一致同意時才能被做出。

TC39的過程

針對ECMAScript特性的每一個提議都需要經歷以下幾個成熟階段,從階段0開始。從一個階段遞交到下一個階段必須要收到TC39的全員同意。

Stage 0:strawman 稻草人

在該階段可以自由的使用任意方式提交推動ECMAScript發展的想法。提議可以來自TC39成員單位,也可以是一個非成員單位, 但需要 注冊成為了TC39的貢獻者

條件:文檔必須要在TC39會議上進行審核,然后將會被添加 階段0的建議頁面中

Stage 1: proposal 提議

階段1是對所提交特性的正式建議。

條件:必須要指派具體的人來負責該提議。該負責人或助理負責人必須是TC39的成員。該提議所解決的問題必須通過描述性的文檔進行說明。 解決方法必須有例子,API,以及對語義和算法的討論。最后,存在的潛在問題也必須要得到區分,例如與其他特性之間的關聯,以及實現的難度。 Implementation-wise,polyfills和demos也都是必須的。

下一步:對于階段1的提議的是否接受,TC39表明了其愿意檢查、討論和為提議做出貢獻。繼續向前,將會是提議的主要變化。

Stage 2: draft 草案

階段2是將會出現標準中的第一個版本。此時,將會與出現在標準中的最終特性是差不多的。

條件:此時建議必須要附加更規范化有關特性的語法和語意的說明(使用ECMAScript標準的正式語言)。 描述應該盡可能的完整,但也可以包含待辦事項列表和占位符。該特性需要兩個實驗性的實現, 但其中一個可以在諸如Babel這樣的轉譯器(transpiler)中。

下一步:從該改階段只接收漸增的變化。

Stage 3: canidate 候選

此時提議已經接近完成,只需要得到提議實現方的反饋,以及由用戶來進一步推動。

條件:標準的文本必須是完備的。指定的審稿人(由TC39指派)和ECMAScript標準的編輯必須在該標準上簽字。 必須要至少有兩個符合標準的實現(可以不指定默認實現)。

下一步:至此之后,只有對實現和使用過程中出現的重大問題進行修正。

Stage 4: finished 完成

提議將被包括到標準之中。

條件:在提議進入該階段時需要滿足以下的條件

  • Test 262 驗收測試(主要是用JavaScript代碼編寫的單元測試來驗證語言特性)
  • 兩個通過測試的符合規范的裝運實現(shipping implementations)
  • 使用該實現的重要的實踐經驗
  • ECMAScript標準的編輯必須要簽署該標準的文本

下一步:該提議會被盡可能快的納入到ECMAScript標準中。當標準通過長達一年的時間獲得通過后,該提議將正式作為標準的其一部分。

不要稱它們為ECMAScript 20xx特性

正如你看到的那樣,只有到了階段4,該特性才會被確定加入到標準中。然后會在下一次的ECMAScript發布中出現該提議, 當然也并非是百分百的,也可能需要更長的時間。因此,你不應該稱提議為“ES7特性”或者“ES2016特性”等等。我通常喜歡的稱法如下:

  • ECMAScript建議:某特性。該建議所處的階段應該在文章的一開始就被說明。
  • ES.stage2: 某特性

如果該提議幾經進入階段4,那么我會稱他為ES20XX特性,當然最安全的做法是等到標準的編輯已經確認該下一個發布會包含該特性后才行。 例如 Object.observe 就是ECMAScript提議被進展到階段2,卻又最終被撤回的個例子。

ECMAScript Stage 3提議

下面這4個特性可能會出現在 ECMAScript 2016 中。

1. 指數操作符

該提議建議使用 ** 操作符作為中綴來實現指數操作:

x ** y

產生的結果等同于

Math.pow(x, y)

例如:

let squared = 3 ** 2; // 9
let num = 3;
num **= 2;
console.log(num); // 9

進一步閱讀可以參考:

2. Array.prototype.include

數組方法 includes 有以下的簽名:

Array.prototype.includes(value : any) : boolean

如果value值是當前接收者(this)的元素的話則返回 true ,否則返回 false

> ['a', 'b', 'c'].includes('a');
ture

> ['a', 'b', 'c'].includes('d'); false</code></pre>

includesindexof 類似——下面兩個表達式幾乎是相等的:

arr.includes(x)
arr.indexOf(x) >= 0

唯一的區別是 includes() 能否發現 NaN ,而 indexof() 不能:

> [NaN].includes(NaN)
true

> [NaN].indexOf(NaN) -1</code></pre>

includes 并不會區分+0和-0( 這也是JavaScript所一直表現的 ):

> [-0].includes(+0)
true

有類型的數組也可以使用 includes() 方法:

let tarr = Unit8Array.of(12, 5, 3);
console.log(tarr.includes(5)); // true

常被問到的問題:

  • 為什么方法叫做 includes ,而不是 contains

后者是最初的選擇,但是對于Web而言會存在問題( MooTools向Array.prototype中增加了這個方法

  • 為什么方法叫做 includes ,而不是 has

has 用于鍵( Map.ptototype.has ), includes 用于元素( String.prototype.includes )。Set中的元素既可以看作是鍵和值, 這就是為什么在Set中有一個 Set.prototype.has ,而沒有 includes

  • ES6的方法 String.prototype.includes 用于字符串,而不是字符。這是否和 Array.prototype.includes 不一致?

如何數組的 includes 和字符串的 includes 工作模式一樣的話,他將接收數組,而不是單個元素。但這兩個 includes 都參照了 indexof 的例子, 字符可以看作為特殊的場景,而有固定長度的字符串則是更常見的場景。

進一步閱讀:

3. SIMD.JS - SIMD APIs + Polyfill

SIMD代表的是“single instruction, multiple data(單指令多數據)”的意思,是CPU有能力將一個操作數應用于值向量(而不是單個值)。 SIMD指令集的一個流行的例子是SSE(Streaming SIMD Extensions),在被Intel處理器所支持。下面是一個簡單的例子:

var a = SIMD.float32x4(1.0, 2.0, 3.0, 4.0);
var b = SIMD.float32x4(5.0, 6.0, 7.0, 8.0);
var c = SIMD.float32x4.add(a, b);

進一步閱讀:

4. 異步函數

在這之前,如果我要介紹異步函數的話,肯定要解釋如何使用Promise和生成器來使用類似于同步的代碼執行異步操作。

使用Promise和生成器來編寫異步代碼:

對于那些需要異步的計算它們的一次性結果的函數而言,作為ES6一部分的Promise,正在變得越來越流行。 其中一個例子就是 客戶端的 fetch API ,它被設計用來取代XMLHttpRequest來獲取文件。 它的使用代碼大致如下:

function fetchJson(url) {
    return fetch(url)
        .then(request => request.next())
        .then(text => {
            return JSON.parse(text);
        })
        .catch(error => {
            console.log(ERROR: ${error.statck});
        });

}

fetchJson('co是一個使用Promise和生成器來允許代碼風格看起來更同步的庫,但也需要使用類似于前面的例子那樣的風格去編碼:

const fetchJson = co(function *() {
    try {
        let request = yield fetch(url);
        let text = yield request.text();
        return JSON.parse(text);    
    } catch (error) {
        console.log(`ERROR: ${error.statck}`);
    }
});

每次回調函數(一個生成器函數)會向co產生一個Promise,回調函數被掛起。一旦Promise被安置好,co便恢復回調函數: 如果Promise被滿足, yield 便返回滿足的值,如果被拒絕, yield 便拋出異常。此外,co能夠promise化回調函數所返回的結果。

異步函數

異步函數是執行類似co行為的專用語法:

async funtion fetchJson(url) {
    try {
        let request = await fetch(url);
        let text = await request.text();
        return JSON.parse(text);    
    } catch(error) {
        console.log(`ERROR: ${error.statck}`);
    }       
}

在內部,異步函數的工作非常類似于生成器,但它并不會被翻譯為生成器代碼:

變種

存在如下一些生成器函數的變種:

  • 異步函數聲明: async function foo() { }
  • 異步函數表達式: const foo = async function () {};
  • 異步方法定義: let obj = { async foo() {} }
  • 異步箭頭函數: const foo = async () => {}

進一步閱讀

閱讀材料

你可以閱讀以下材料來深入的理解本文中涉及到的內容:

其他閱讀材料:

來自: http://wwsun.github.io/posts/new-in-es2016.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!