ECMAScript 2018 標準導讀

前言

本文是對《ECMAScript 2018 Language Specification》的解讀。
本文是對標準的概述性導讀,不是對 ES2018特性的詳細描述,也不會針對某個技術點進行詳細展開,可是會附上相關文章外鏈。javascript

規格介紹

整個文檔有引言+27個章節+7篇附錄,大概五六百頁的樣子。html

引言和前面3章部分,都是在講規格自己,跟JS語言自己無關。內容不多,能夠快速過一遍。java

  • Introduction 部分 介紹了語言歷史和標準化歷程;
  • 前3章 ScopeConformanceNormative References 主要介紹了文檔的範圍、一致性和參考文獻。所謂一致性,其實是標準實現的一致性,任何實現ECMAScript 標準的語言,都必須徹底實現文檔中描述的語法和語義,而且能夠有規格以外的自定義程序語法。

語言概述

第4章 Overview 是對語言的總體介紹。涵蓋了Web腳本語言環境、ES基本概念和專業術語,以及嚴格模式的簡單介紹。這裏跟你們分享幾個有意思的點。git

奇葩的面向對象機制

ECMAScript is an object-oriented programming language for performing computations and manipulating computational objects within a host environment.
ES是一門面向對象的語言,這是官方描述!( 這有什麼奇怪的啊,你們都知道啊)可是ES的面向對象設計機制倒是不同凡響,大有學問( 這有什麼啊,不就原型鏈嘛)。咱們多少都瞭解一些,但要徹底講清楚,恐怕專門開一篇博客也不夠。

但我仍是嘗試專門寫了一篇:《如何優雅的解讀JS的面向對象機制》es6

腳本語言的逆襲

ECMAScript was originally designed to be used as a scripting language, but has become widely used as a general-purpose programming language.

這個就有點屌了,ES最初是被拿來當Web腳本語言用的,但如今已經成了時下最流行的通用編程語言之一。此中原因你們應該也很清楚,很少說,只是抒發一下感慨:Always bet on JS可不是亂說的。github

有關對象的描述

本章還列舉出了JS中的專業名詞及解釋,好比類型、原始值、對象、構造器、原型......等概念。有意思的是標準中關於對象的描述在ES5裏面有三種:算法

  • native object(原生對象),指語義徹底由規範定義而且不摻雜任何宿主環境定義的的對象;
  • build-in object(內置對象),由ECMA實現提供,程序執行時就存在的對象。全部內置對象都是原生對象。
  • host object(宿主對象),由執行環境提供,好比瀏覽器的window對象和history對象。JS裏的對象不是原生對象就是宿主對象。

可是在ES6以後就改爲了四種:編程

  • ordinary object:普通對象,只要具有了對象的全部基本內置方法就能夠了。
  • exotic object:外來對象,若是不具有標準對象全部的基本內置方法,就是外來對象。JS裏的對象不是普通對象就是外來對象。
  • standard object:標準對象,語義由本規範定義的對象。
  • built-in object:內置對象,跟ES5中描述同樣。

對比來看,前者是以宿主環境爲劃分條件,後者則是以對象的基本內置方法。ES6以後其實劃分的更細了。數組

記法約定

第5章 Notational Conventions 詳細介紹了規範描述中用到的一些句法、詞法以及算法約定等內容,若是要看懂後面的有關語法行爲,函數實現的詳細描述,就得看懂這章,看完以後你甚至能夠照着標準實現一遍。瀏覽器

這章涉及大量編譯基本知識,仍是強烈建議花些時間看下,否則後面可能無法繼續。你須要知道如下概念:

上下文無關文法

做爲ECMAScript規格文檔,天然須要用一種專業的方式來描述這門語言,這種專業的描述語言的方法,就是所謂的文法(文法由若干產生式組成)。而上下文無關的意思,就是全部產生式的左邊只有一個非終結符,由於只有這樣,產生式右邊的串才能規約到左邊的非終結符,不然就是上下文相關。大部分編程語言都是上下文無關文法,ECMAScript也不例外。

詞法、正則文法、數字字符串文法和句法約定

一個冒號「:」做爲分隔符分割句法的產生式。兩個冒號「::」做爲分隔符分割詞法和正則的文法產生式。詞法和正則的文法共享某些產生式。三個冒號「:::」做爲分隔符分割數字字符串文法的產生式。而後列舉了各類句法,文法標記,總之不少概念,此處不展開。

內部機制

第6到8章詳細描述了語言運行的內部機制,從宏觀上對ES進行描述,包括數據類型和值,語言內部的抽象操做,以及代碼執行的上下文相關知識。

類型

ES中的類型可細分爲ES語言類型和規範類型,語言類型對應的是程序中直接被操做的值的類型,包括Undefined,Null,Boolean,Number,String,Object,Symbol。理解類型,是理解這門語言的基礎。

首先是Undefind和Null,兩者區別可參考 undefined與null的區別 - 阮一峯。在一門編程語言中對於「空」的描述用到了兩種基本類型,估計只有JavaScript了。其實一開始只有null,後來爲了解決類型轉換和錯誤處理問題引入了undefined。

undefined 表示此處應該有個值,可是這個值還沒給出來,其實就是佔了個坑,這個坑是語言內部實現幫你作的,你不用管。null 纔是真正意義上的空值,表示對象世界中的「無」。正所謂道生一,一輩子二,二生三,三生萬物。JS中萬物皆對象,全部對象的原型鏈均可以上溯到惟一的Object,而Object的原型,正是萬物之始源,混沌之道null。因此JS中null的意義遠超其餘編程語言,這正是讓JS的面向對象思想與道家哲學完美契合的重要一筆。

因此我的理解,Undefined雖然做爲基本類型,解決的倒是語言內部處理問題,因此永遠不要在代碼中主動出現,要在語義上處理空就用null。全部由於undefined帶來的問題,基本上是佔着茅坑不拉屎的行爲致使。因此google在Dart中就只有null,而沒有undefined,由於undefined解決的問題徹底能夠在語言內部解決,不必暴露給用戶。

Boolean和Symbol沒啥好說的,數值的設計也是從簡,只有一個Number類型。有意思的是String,官方對於String類型的描述:

The String type is the set of all ordered sequences of zero or more 16-bit unsigned integer values (「elements」) up to a maximum length of 2e53 - 1 elements.
翻譯過來就是指全部有限的零個或多個16位無符號整數值的有序序列(共計2e53 - 1個元素)。這個2e53 - 1是怎麼來的呢,按照16位無符號整數值計算的話?

更有意思的是,String中的每個字符都被視爲獨立的UTF-16代碼單元,即佔2個字節,做用在字符串上的全部操做都視它們爲無差異的16位無符號整數(這裏的UTF-16,實際上是指內部實現,計算機內存中都是基於unicode編碼的,只是在存儲或讀取時會進行UTF-8或者其餘編碼類型轉換)。可是UTF-16卻有兩種長度的字符,U+0000到U+FFFF之間的字符佔2個字節,U+10000到U+10FFFF之間的字符佔4字節。對於4字節的字符ES是沒法準確處理的,須要本身去根據編碼值狀況判斷,這也是一大坑爹之處。

對此,我也專門寫了一篇:《深刻理解JavaScript中的String類型-未發佈》

除了以上語言類型,整個規範中還有用於描述這門語言的規範類型,規範類型的值是規範本身造的,有的仍是ES表達式計算的中間結果,因此不必對應到特定的語言類型上。若非特別說明,ES中的類型一般指語言類型。

操做摘要

類型之間會涉及到各類運算,這就會涉及到各類操做運算。好比類型轉換涉及到的內部機制和算法流程,7.1 Type Conversion 都有詳細說明。7.2 Testing and Comparison Operations 講了測試和比較操做,好比測試一個對象是不是數組,是否數字,是否構造函數,以及 ===== 的定義等等。以數組測試操做isArray(argument)爲例,標準中的描述以下:

1. If Type(argument) is not Object, return false.
2. If argument is an Array exotic object, return true.
3. If argument is a Proxy exotic object, then
    a. If argument.[[ProxyHandler]] is null, throw a TypeError exception.
    b. Let target be argument.[[ProxyTarget]].
    c. Return ? IsArray(target).
4. Return false.

相對於ES5來講,規範中增長了對Proxy的處理。咱們再看 underscope v1.8.3 源碼中對isArray的實現:

_.isArray = Array.isArray || function(obj) {
    return toString.call(obj) === '[object Array]';
}

相對於ES5來講,規範中增長了對Proxy的處理,目前來看這是引擎內部處理的,對如今不少檢測數組的方法並不影響。

語言實現細節

這是個大坑,仍是附上ES2018正式版規範地址吧:

https://www.ecma-internationa...

若是想快速瞭解一下新特性,能夠看這裏:

https://medium.com/front-end-...

具體有哪些 finished proposals 能夠參考 tc39 的 GitHub

如何優雅的閱讀ECMA標準

因爲目前使用最爲普遍的仍是ECMA 5.1版本,因此在閱讀ES2018以前,建議先把5.1的標準看一遍,方便對比。好在W3C中文站有5.1的100%翻譯版本:

ES5中文版: https://www.w3.org/html/ig/zh...

而後能夠再看ES6也就是ES2015的標準,雖然沒有中文版,不過能夠參考阮老師的ES6入門,順便也能夠瞄一眼ES2016的標準:

ES 2015: http://www.ecma-international...
ECMAScript 6入門教程: http://es6.ruanyifeng.com/
ES 2016: http://www.ecma-international...

期間有任何疑惑能夠參考MDN上的JS參考文檔,很是全面,涵蓋了從入門到精通。

https://developer.mozilla.org...

看完這些再看ES2018就會很是輕鬆了:

https://tc39.github.io/ecma262/
相關文章
相關標籤/搜索