ECMAScript ? 2018 Language Specification

介紹

Ecma標準定義了ECMAScript 2018語言。這是第9版的ECMAScript規(guī)范。自1997發(fā)布第一版以來,ECMAScript已經發(fā)展為世界上最廣泛使用的通用編程語言之一。它最被人熟知的是作為Web瀏覽器中的嵌入語言,但是也被廣泛運用在服務器和嵌入式程序中。

ECMAScript基于一些原始技術,最著名的是JavaScript(Netscape)和JScript(微軟)。這個語言是由Brendan Eich在網景公司發(fā)明的,第一次出現是在公司的Navigator2.0瀏覽器上。它出現在所有網景的后續(xù)瀏覽器,以及微軟Internet Explorer 3.0開始的瀏覽器中。

ECMAScript語言規(guī)范的開發(fā)從1996年11月開始。第一版Ecma標準在1997年6月的Ecma大會上被采用。

ECMA標準被提交到ISO/IEC JTC 1在快速通道程序下采用,并且在1998年4月被批準作為ISO/IEC 16262國際標準。ECMA大會1998年6月批準了第二版ECMA -262使它完全符合ISO/IEC 16262。第一版和第二版之間的變化本質上只是編輯整理。

第三版標準引入了強大的正則表達式,更好的字符串處理,新增控制語句,try /catch異常處理機制、更嚴格的錯誤定義,格式化數字輸出。次要變化是預期了未來語言的發(fā)展變化。第三版的ECMAScript標準在1999年12月的被ECMA大會采用并且在2002年6月發(fā)布為ISO/IEC 16262:2002。

第三版出版后,ECMAScript與萬維網的結合被廣泛采用,它基本上已經成為被所有的網絡瀏覽器所支持的編程語言。在開發(fā)ECMAScript第四版時做了一些重要的改動。然而,這些工作沒有完成,ECMAScript第四版也沒有發(fā)布,但有些內容被納入第六版的開發(fā)中。

ECMAScript的第五版(ECMA - 262年出版的第五版)編輯整理了已經成為常見瀏覽器的實現的語言規(guī)范并且增加了對自從第三版出版以來就出現的新特性的支持。這些特性包括訪問器屬性,反射創(chuàng)建和檢查對象,程序控制的屬性特性,額外的數組操作功能,支持JSON對象編碼格式,和提供更強的錯誤檢查和程序安全的嚴格模式。第五版在2009年12月被ECMA大會采用。

第五版被提交到ISO/IEC JTC 1在快速通道程序下采用, 并且被批準作為國際標準ISO/IEC 16262:2011。ECMAScript的5.1版標準包含微小的改動,文本與ISO/IEC16262:2011相同。2011年6月ECMA大會通過5.1版。

第六版的重點開發(fā)始于2009年,第五版也正在準備出版。然而,這是基于重要的實驗和語言增強設計工作,這項工作可以追溯到在1999年出版的第三版。確切地說,完成第六版是十五年來努力的結果。額外的目標包括為大型應用提供更好的支持,庫的創(chuàng)建以及將ECMAScript作為其他語言的編譯目標。主要的增強包括模塊,類的生命,詞法塊作用域,迭代器和生成器,異步編程的promises,解構模式和尾部調用。ECMAScript內置庫擴展支持額外的數據抽象,包括maps,sets和二進制數組,同時在字符串和正則表達式中也額外支持Unicode supplemental characters。內置庫可以通過子類擴展。第六版提供基礎的正則、增量語言和庫增強。第六版在2015 年 6 月被大會采納。

ECMAScript 2016是在 ECMA TC39 新的逐年發(fā)布的節(jié)奏和開放開發(fā)進程下發(fā)布的第一個 ECMAScript版本。一個純文本源文件從 ECMAScript 2015源文件中被集成到GitHub服務器上作為未來完全開發(fā)的基礎 。在標準發(fā)展經歷的一年中,數以百計的 pull requests 和 issues 被提出,數以千計的 bug改正、描述性修復,以及其他的改進。此外,許多幫助性軟件工具被開發(fā)出來,包括 Ecmarkup、Ecmarkdown 和 Grammarkdown。ES2016 還支持一個新的冪運算符、為 Array.prototype 新增一個名為 includes 的方法。

ECMAScript 2017引入了異步函數、共享內存,原子化小型的語言和庫增強、bug修復和編輯更新。異步函數通過為promise-returning函數提供語法來改善異步編程體驗。共享內存和原子學引入了一種新的內存模型,該模型允許多代理程序使用原子操作進行通信,原子操作甚至在并行CPU上也能確保定義良好的執(zhí)行順序。該規(guī)范還包括關于Object的新靜態(tài)方法:Object.values,Object.entries和Object.getOwnPropertyDescriptors。

本規(guī)范第9版通過異步迭代器協議和異步生成器引入了對異步迭代的支持。該規(guī)范還包括四個新的正則表達式特性:dotAll標志、命名的捕獲組、Unicode屬性轉義和后視斷言。它還包括REST參數和擴展運算符支持對象屬性。也有許多小的更新,編輯和規(guī)范,有許多貢獻來自我們敬畏的社區(qū)。

代表許多組織的數十位個人在Ecma TC39中對本版和先前版本的發(fā)展作出了非常重要的貢獻。此外,一個充滿活力的社區(qū)已經出現,為支持TC39的ECMAScript而努力。這個社區(qū)已經審查了許多草稿,提交了數千個bug報告,進行實驗,貢獻了測試套件,并向全世界的開發(fā)人員社區(qū)介紹了ECMAScript。不幸的是,我們不可能識別并答謝為這一努力做出貢獻的每個人和組織。

Allen Wirfs-Brock
ECMA-262, 6th Edition Project Editor

Brian Terlson
ECMA-262, 7th Edition Project Editor

1 范圍

此標準定義了ECMAScript 2018 通用編程語言。

2 一致性

符合標準的ECMAScript實現,必須提供和支持本規(guī)范中所有的類型,值,對象,屬性,函數和語法及語義。

符合標準的ECMAScript實現, 源文本必須與最新版的Unicode標準和ISO/IEC 10646一致。

符合標準的ECMAScript實現提供了一個應用程序編程接口,該API支持需要適應不同人類語言和國家使用的語言和文化約定同時必須實現與本規(guī)范兼容的ECMA-402最新版所定義的接口的程序。

符合標準的ECMAScript實現可以提供超出本規(guī)范中描述的類型、值、對象、屬性和功能。特別地,符合標準的ECMAScript實現可以為本規(guī)范中描述的對象提供本規(guī)范中未描述的屬性以及這些屬性的值。

符合標準的ECMAScript實現可以支持本規(guī)范中未描述的程序和正則表達式語法。特別地,符合標準的ECMAScript實現可以支持使用本規(guī)范的子句11.6.2.2中列出的“未來保留字”的程序語法。

符合標準的ECMAScript實現不能實現子句16.2中列出為禁止擴展的任何擴展。

3 引用標準

以下參考文獻對于本文件的應用是必不可少的。對于過時的參考文獻,只有引用的版本適用。未注明日期的參考文獻,引用文件的最新版本(包括任何修訂)適用。

ISO/IEC 10646信息技術-通用多八位編碼字符集(UCS)附加修訂1:2005、修訂2:2006、修訂3:2008和修訂4:2008,附加額外的修改和更正,或繼承。

ECMA-402, ECMAScript 2015 國際化API規(guī)范.
https://ecma-international.org/publications/standards/Ecma-402.htm

ECMA-404, JSON數據轉換格式.
https://ecma-international.org/publications/standards/Ecma-404.htm

4 概述

本節(jié)包含一個非規(guī)范化的ECMAScript語言概述。

ECMAScript是一種面向對象的編程語言,用于在主機環(huán)境中進行計算和操作計算對象。這里定義的ECMAScript不打算在計算上是自給自足的;事實上,在本說明書中沒有用于輸入外部數據或輸出計算結果的規(guī)定。相反,預期的ECMAScript程序的計算環(huán)境不僅提供本規(guī)范中描述的對象和其他設備,而且還提供描述和行為超出本說明書的范圍的特定環(huán)境的指定對象。指示它們可以提供可訪問的特定屬性和可從ECMAScript程序調用的特定函數。

ECMAScript最初被設計用作腳本語言,但是現在已經被廣泛用作通用編程語言。腳本語言是一種編程語言,用于操縱、定制和自動化現有系統(tǒng)的設備。在這樣的系統(tǒng)中,有用的功能已經可以通過用戶界面獲得,并且腳本語言的機制是向程序控制公開該功能。以這種方式,現有系統(tǒng)被認為提供了對象和設備的主機環(huán)境,從而完成了腳本語言的功能。腳本語言旨在供專業(yè)人員和非專業(yè)程序員使用。

ECMAScript最初被設計成一種Web腳本語言,提供了一種機制來激活瀏覽器中的網頁,并作為基于Web的客戶端-服務器體系結構的一部分來執(zhí)行服務器計算。ECMAScript現在用于為各種主機環(huán)境提供核心腳本能力。因此,在本文檔中指定的核心語言是脫離任何特定的主機環(huán)境之外的。

ECMAScript的使用已經超越了簡單的腳本,現在它已用于許多不同環(huán)境和規(guī)模中的全部編程任務。隨著ECMAScript使用的擴展,它提供的特性和工具也在擴展。ECMAScript現在是一個功能齊全的通用編程語言。

一些ECMAScript的工具和在其他編程語言中使用的類似;特別是 C、java?、Self。設計方案描述如下:
ISO/IEC 9899:1996, Programming Languages – C.

Gosling, James, Bill Joy and Guy Steele. The Java? Language Specification. Addison Wesley Publishing Co., 1996.

Ungar, David, and Smith, Randall B. Self: The Power of Simplicity. OOPSLA '87 Conference Proceedings, pp. 227-241, Orlando, FL, October 1987.

IEEE Standard for the Scheme Programming Language. IEEE Std 1178-1990.

4.1 網頁腳本

Web瀏覽器提供用于客戶端計算的ECMAScript主機環(huán)境,包括例如表示窗口、菜單、彈出窗口、對話框、文本區(qū)域、錨、幀、歷史、cookie和輸入/輸出的對象。此外,主機環(huán)境提供了一種將腳本代碼附加到事件(如焦點改變、頁面和圖像加載、卸載、錯誤和中止、選擇、表單提交和鼠標操作)的方法。腳本代碼出現在HTML中,顯示的頁面是用戶界面元素和固定且計算出的文本和圖像的組合。腳本代碼響應用戶交互,并且不需要主程序。

Web服務器為服務器端的計算提供了不同的主機環(huán)境。包括對象表示請求,客戶端,和文件;鎖定和共享數據的機制。通過使用瀏覽器端和服務器端的腳本,可以為基于Web的應用程序提供定制的用戶界面并分配客戶端和服務器之間的計算能力。

支持ECMAScript的每個Web瀏覽器和服務器都提供自己的主機環(huán)境,從而完成ECMAScript執(zhí)行環(huán)境。

4.2 ECMAScript 概述

下面是ECMASScript的非正式概述--不包含語言的所有部分。這個概述不是標準的一部分。

ECMAScript是基于對象的:基本語言和主機設備由對象提供,ECMAScript程序是一組通信對象。在ECMAScript中,對象是零個或多個屬性的集合,每個屬性都具有確定如何使用每個屬性的屬性——例如,當屬性的可寫屬性設置為false時,任何執(zhí)行ECMAScript代碼為屬性分配不同值的嘗試都會失敗。屬性是保存其他對象、原始值或函數的容器。原始值是下列內置類型成員之一:Undefined、Null、Boolean、Number、String和Symbol;對象是內置類型Object的成員;函數是可調用對象。通過屬性與對象相關聯的函數稱為方法。

ECMAScript定義了一組集合了ECMAScript實體定義的內置對象。這些內置對象包括全局對象;對語言的運行時語義至關重要的對象,包括對象、函數、布爾、符號和各種錯誤對象;表示和操作數值的對象,包括Math、Number和Date;文本處理對象String和RegExp;作為值的索引集合的對象,包括Array和9種不同類型的Typed Array,它們的元素都具有特定的數字數據表示;鍵控集合,包括Map和Set對象;支持結構化數據的對象,包括JSON對象、ArrayBuffer、SharedArrayBuffer和DataView;支持包括生成器函數和Promise對象的控件抽象的對象;以及包括Proxy和Reflect的反射對象。

EcMAScript還定義了一組內置運算符。ECMAScript運算符包括各種一元運算、乘法運算符、加法運算符、位移位運算符、關系運算符、相等運算符、二進制位運算符、二進制邏輯運算符、賦值運算符和逗號運算符。

大型ECMAScript程序由模塊支持,這些模塊允許程序被劃分為多個語句和聲明序列。每個模塊顯式地標識它使用的需要由其他模塊提供的聲明,以及哪些聲明可供其他模塊使用。

ECMAScript語法有意效仿Java語法。EcMAScript語法是寬松的,使它能夠作為一種易于使用的腳本語言。例如,不需要聲明變量的類型,也不需要將變量的類型與屬性相關聯,并且在調用函數之前不需要以文本形式聲明它們的定義。

4.2.1 對象

盡管ECMAScript包含類定義的語法,但是EcMAScript對象不是根本上基于類的,例如C++、SimalTalk或Java中的類。相反,可以以各種方式創(chuàng)建對象,包括通過文字符號或通過創(chuàng)建對象的構造函數,然后執(zhí)行通過將初始值分配給對象的屬性來初始化所有或部分對象的代碼。每個構造函數都有一個名為“prototype”的屬性,用于實現基于原型的繼承和共享屬性。對象是通過使用new表達式中的構造函數創(chuàng)建的;例如,new Date(2009,11)創(chuàng)建新的日期對象。調用構造函數而不使用new構造函數會產生依賴于構造函數的結果。例如,Date()會生成當前日期和時間的字符串表示形式,而不是對象。

構造函數創(chuàng)建的每個對象都對其構造函數的“prototype”屬性的值具有隱式引用(稱為對象的原型)。此外,原型可能對其原型具有非空隱式引用,依此類推;這稱為原型鏈。當引用對象中的屬性時,該引用是指原型鏈中第一個包含該名稱屬性的對象中該名稱的屬性。換句話說,首先檢查直接提到的對象是否具有這樣的屬性;如果該對象包含命名屬性,即引用所引用的屬性;如果該對象不包含命名屬性,則接下來檢查該對象的原型;等等。



在基于類的面向對象語言中,一般情況下,狀態(tài)由實例承載,方法由類承載,而繼承僅具有結構和行為。在ECMAScript,狀態(tài)和方法是由對象攜帶的,結構、行為和狀態(tài)都是繼承的。

所有不直接包含其原型包含的特定屬性的對象共享該屬性及其值。圖1說明了這一點:

CF是一個構造函數(也是一個對象)。使用new表達式創(chuàng)建了五個對象:cf1、cf2、cf3、cf4cf5。這些對象中的每一個都包含名為q1q2的屬性。虛線表示隱式原型關系,因此,例如cf3的原型是CFP。構造函數CF有兩個屬性,名為P1P2,它們對于CFP、cf1、cf2、cf3、cf4cf5不可見。CFPCFP1的屬性由cf1、cf2、cf3、cf4cf5(而不是CF)共享,CFP隱式原型鏈中未命名為q1、q2CFP1的任何屬性也是如此。請注意,CFCFP之間沒有隱式原型鏈接。

與大多數基于類的對象語言不同,屬性可以通過向對象賦值來動態(tài)地添加到對象。也就是說,構造函數不需要對所有或任何構造對象的屬性命名或賦值。在上面的圖中,可以通過為CFP中的屬性分配新值來為cf1、cf2、cf3、cf4cf5添加新的共享屬性。

盡管ECMAScript對象本質上不是基于類的,但基于構造函數、原型對象和方法的公共模式定義class-like的抽象模式很方便。EcMAScript內置對象本身遵循這樣的class-like模式。從ECMAScript 2015開始,ECMAScript語言包括語法類定義,允許程序員簡潔地定義與內置對象使用的抽象模式相同的類。

4.2.2 ECMAScript的嚴格模式變體

ECMAScript語言認識到該語言的一些用戶可能希望限制他們對該語言中可用的一些特征的使用的可能性。他們這樣做可能是為了安全,避免他們認為是容易出錯的特性,得到增強的錯誤檢查,或者出于他們選擇的其他原因。為了支持這種可能性,ECMAScript定義了一種嚴格的語言變體。該語言的嚴格變體排除了常規(guī)ECMAScript語言的一些特定的語法和語義特征,并修改了一些特征的詳細語義。嚴格變體還指定了額外的錯誤條件,在語言的非嚴格形式沒有指定為錯誤的情況下,必須通過拋出錯誤異常來報告這些條件。

ECMAScript的嚴格變體通常被稱為嚴格的語言模式。選擇和使用ECMAScript的嚴格模式語法和語義是在單個ECMAScript源文本單元的級別上實施的。因為嚴格模式是在語法源文本單元的級別上選擇的,所以嚴格模式僅強加在這種源文本單元內具有局部效果的限制。嚴格模式不限制或修改必須跨多個源文本單元一致操作的ECMAScript語義的任何方面。完整的ECMAScript程序可以由嚴格模式和非嚴格模式ECMAScript源文本單元組成。在這種情況下,嚴格模式僅適用于實際執(zhí)行在嚴格模式源文本單元中定義的代碼時。

為了符合這個規(guī)范,ECMAScript實現必須同時貫徹全面無限制的腳本語言和按本規(guī)范定義的腳本語言的嚴格變體。此外,實現必須支持無限制源文本單元和嚴格模式源文本單元組合成一個單一的復合程序。

4.3 術語和定義

以下術語和定義適用于本文檔

4.3.1 類型(type)

本規(guī)范第6章中定義的數據值集合

4.3.2 原始值(primitive value)

第6章中定義的Undefined、Null、Boolean、Number、Symbol 或 String 類型之一

注意 原始值是直接在語言實現的最底層上表示的數據

4.3.3 對象(object)

Object類型中的成員

注意 對象是屬性的集合,并且具有單個原型對象。原型可以是null。

4.3.4 構造函數(constructor)

函數對象,用于創(chuàng)建和初始化對象。

注意 構造函數的prototype屬性的值是用于實現繼承和共享屬性的原型對象。

4.3.5 原型(prototype)

對象,為其他對象提供共享屬性。

注意 當構造函數創(chuàng)建一個對象時,該對象隱式引用構造函數的prototype屬性,以便解析屬性引用。構造函數的prototype屬性可以由程序表達式constructor.prototype引用,添加到對象原型的屬性通過繼承由共享原型的所有對象共享?;蛘撸梢允褂?code>Object.create內置函數使用顯式指定的原型創(chuàng)建新對象。

4.3.6 普通對象(ordinary object)

對象,該對象對于所有對象必須支持的基本內部方法具有默認行為。

4.3.7 外來對象(exotic object)

對象,該對象不具有一個或多個基本內部方法的默認行為。

注意 任何不是普通對象的對象都是外來對象。

4.3.8 標準對象(standard object)

對象,其語義由本規(guī)范定義。

4.3.9 內置對象(built-in object)

由ECMAScript實現指定和提供的對象。

注意 本規(guī)范中定義了標準內置對象。ECMAScript實現可以指定和提供其他類型的內置對象。內置構造函數是一個內置對象,也是一個構造函數。

4.3.10 未定義值(undefined value)

當變量未賦值時使用的原始值。

4.3.11 未定義類型(Undefined type)

唯一值為未定義值的類型。

4.3.12 空值(null value)

表示對象缺省值的原始和值。

4.3.13 空類型(Null type)

唯一值為空值的類型。

4.3.14 布爾值(Boolean value)

布爾類型的成員。

注意 只有兩個布爾值, true 和 false

4.3.15 布爾類型(Boolean type)

由原始值 true 和 false 組成的類型。

4.3.16 布爾對象(Boolean object)

對象類型的成員,該對象類型是標準內置布爾構造函數的實例。

注意 通過在new表達式中使用布爾構造函數創(chuàng)建布爾對象,將布爾值作為參數提供。結果對象有一個內部插槽,其值是布爾值。布爾對象可以強制轉換為布爾值。

4.3.17 字符串值(String value)

原始值,零個或多個16位無符號整數的有限有序序列。

注意 字符串值是字符串類型的成員。序列中的每個整數值通常表示UTF-16文本的單個16位單元。但是,除了它們必須是16位無符號整數,ECMAScript對這些值沒有任何限制或要求。

4.3.18 字符串類型(String type)

所有可能的字符串值的集合。

4.3.19 字符串對象(String object)

對象類型的成員,該對象是標準內置字符串構造函數的實例。

注意 通過使用new表達式中的字符串構造函數創(chuàng)建字符串對象,將字符串值作為參數提供。結果對象有一個內部插槽,其值是字符串值。通過調用字符串構造函數作為函數(21.1.1.1),可以將字符串對象強制轉換為字符串值。

4.3.20 數值(Number value)

原始值,對應雙精度64位二進制格式IEEE 754-2008值。

注意 數值是數字類型的成員,是數字的直接表示。

4.3.21 數字類型(Number type)

所有可能的數值包括一個特殊的“非數字”(NaN)值、正無窮大和負無窮大的集合。

4.3.22 數字對象(Number object)

對象類型的成員,該對象是標準內置數字構造函數的實例。

注意 通過使用new表達式中的數字構造函數創(chuàng)建一個數字對象,提供一個數字值作為參數。結果對象有一個內部插槽,其值是數字值。通過調用數字構造函數作為函數(20.1.1.1),可以將一個數字對象強制轉換為一個數字值。

4.3.23 無窮(Infinity)

正無窮大的數值。

4.3.24 非數字(NaN)

值為IEEE 754-2008“非數值”的數值。

4.3.25 符號值(Symbol value)

原始值,表示唯一的非字符串對象屬性值。

4.3.26 符號類型(Symbol type)

所有可能的符號值的集合。

4.3.27 符號對象(Symbol object)

對象類型的成員,該對象是標準內置符號構造函數的實例。

4.3.28 函數(function)

可以作為子程序調用的對象類型的成員。

注意 除了其屬性之外,函數還包含可執(zhí)行代碼和狀態(tài),該狀態(tài)決定調用時的行為。函數的代碼可以在ECMAScript編寫,也可以不在其中編寫。

4.3.29 內置函數(built-in function)

作為函數的內置對象。

注意 內置函數的示例包括parseIntMath.exp。實現可以提供本規(guī)范中沒有描述的依賴于實現的內置函數。

4.3.30 屬性(property)

對象的一部分,將鍵(字符串值或符號值)與值關聯。

注意 根據屬性的形式,該值可以直接表示為數據值(原始值、對象或函數對象),也可以間接表示為一對訪問器函數。

4.3.31 方法(method)

作為屬性的值的函數。

注意 當一個函數被調用為一個對象的方法時,該對象作為函數的this值傳遞給函數。

4.3.32 內置方法(built-in method)

作為內置函數的方法。

注意 本規(guī)范中定義了標準的內置方法,ECMAScript實現可以指定并提供其他附加的內置方法。

4.3.33 特性(attribute)

定義屬性的某些特性的內部值。

4.3.34 自有屬性(own property)

對象直接包含的屬性。

4.3.35 繼承屬性(inherited property)

不是對象本身的屬性,而是對象原型的屬性(無論是自己的還是繼承的)。

4.4 本規(guī)范的組織

本規(guī)范的其余部分組織如下:
第5章定義了整個規(guī)范中使用的符號約定。
第6-9章定義了ECMAScript程序運行的執(zhí)行環(huán)境。
第10-16章定義了實際的ECMAScript編程語言,包括其語法編碼和所有語言特性的執(zhí)行語義。
第17-26章定義了ECMAScript標準庫。它們包括ECMAScript程序在執(zhí)行時可用的所有標準對象的定義。
第27章描述了SharedArrayBuffer后備內存訪問的內存一致性模型和原子對象的方法。

5 記法約定

5.1 語法和詞法的文法

5.1.1 上下文無關文法

一個上下文無關文法由一定數量的產生式(productions)組成。每個產生式的左邊 (left-hand side) 是一個被稱為非終結符(nonterminal)的抽象符號,右邊 (right-hand side) 是零或多個非終結符和終結符(terminal symbols)的有序排列。任何文法,它的終結符都來自指定的字母集。

鏈式產生式是指在其右側正好具有一個非終結符號以及零個或多個終結符號的產生式。

當從一個叫做目標符(goal symbol)的特殊非終端符組成的句子起始,那么給出的上下文無關文法就表示語言(language),即,將產生式右邊序列的非終結符當作左邊,進行反復替換的結果就成為可能的終結符序列集合(可能無限)。

5.1.2 詞法和正則的文法

第11章給出了ECMAScript的詞法文法(lexical grammar)。作為此文法的終結符字符(Unicode代碼單元)符合第 10.1章定義的 SourceCharacter 的規(guī)則。它定義了一套產生式,從目標符 InputElementDiv,InputElementTemplateTail,InputElementRegExp或TemplateTail起始,描述了如何將這樣的字符序列翻譯成一個輸入元素序列。

空白和注釋之外的輸入元素構成ECMAScript語法文法的終結符,它們被稱為ECMAScript tokens。這些tokens是ECMAScript語言的保留字,標識符,字面量,標點符號。此外,行結束符雖然不被視為tokens,但會成為輸入元素流的一部分,用于引導處理自動插入分號(11.9)??瞻缀蛦涡凶⑨寱缓唵蔚膩G棄,不會出現在語法文法的輸入元素的流中。如果一個多行注釋 (MultiLineComment)(即形式為“/ ... /”的注釋,不管是否跨越多行)不包含行結束符也會簡單地丟棄,但如果一個多行注釋包含一個或多個結束符,那么,注釋會被替換為一個行結束符,成為語法文法輸入元素流的一部分。

21.2.1給出了ECMAScript的正則文法(RegExp grammar)。此文法的終結符字符也由SourceCharacter定義。它定義了一套產生式,從目標符Pattern起始,描述了如何將這樣的字符序列翻譯成一個正則表達式模式。

兩個冒號“::”作為分隔符分割詞法和正則的文法產生式。詞法和正則的文法共享某些產生式。

5.1.3 數字字符串文法

用于轉換字符串為數字值的一種文法。此文法與詞法文法的一部分(與數字字面量有關的)類似,并且有終結符SourceCharacter。此文法出現在 7.1.3.1 。

三個冒號“:::”作為分隔符分割數字字符串文法的產生式。

5.1.4 語法文法

第11,12,13,14 和15章給出了ECMAScript的語法文法 。詞法文法定義的ECMAScript tokens是此文法的終結符(5.1.2)。它定義了一組起始于兩個可替換目標符Script和Module的產生式,描述了語法正確的ECMAScript程序獨立組件應該怎樣排列tokens。

當代碼點流被解析為ECMAScript腳本或模塊時,首先通過重復應用詞法文法將其轉換為輸入元素流;然后再用一個語法文法應用程序解析這個輸入元素流。當輸入元素流沒有更多 tokens時,如果輸入元素流中的token不能被解析為目標非終結符(腳本或模塊)的單個實例,那么輸入流在語法上是錯誤的。

當解析成功時,它構建一個解析樹,一個根樹結構,其中每個節(jié)點是一個解析節(jié)點。每個解析節(jié)點是語法中符號的實例;它表示可以從該符號派生的源文本的跨度。解析樹的根節(jié)點代表整個源文本,是解析目標符號的實例。當一個解析節(jié)點是非終結符的實例時,它也是那個非終結符作為左側的一些產生式的實例。此外,它具有零個或多個子節(jié)點,每個都對應產生式右側的每個符號:每個子節(jié)點是一個解析節(jié)點,它是相應符號的實例。

解析器的每次調用都會實例化新的解析節(jié)點,并且即使在解析相同的源文本之間也不會重復使用解析節(jié)點。解析節(jié)點被認為是相同的解析節(jié)點,當且僅當它們表示相同的源文本跨度、是同一語法符號的實例,并且由相同的解析器調用產生。

注意 多次解析同一字符串會導致不同的解析節(jié)點,例如:
eval(str); eval(str);

注意 解析節(jié)點是規(guī)范的偽事實,并且不需要使用類似的數據結構來實現。

只用一個冒號“:”作為分隔符分割語法文法的產生式。

事實上第12,13,14 和 15 章給出的語法語法,并不能完全說明一個正確的ECMAScript腳本或模塊能接受的token序列。一些額外的token序列也被接受,即某些特殊位置(如行結束符前)加入分號可以被文法接受。此外,文法描述的某些 token 序列不被文法接受,如一個行結束符出現在“尷尬”的位置。

在某些情況下,為了避免歧義,語法文法使用廣義的產生式,允許token序列不形成有效的ECMAScript腳本或模塊。例如,該技術用于對象字面量和對象解構模式。在這種情況下,提供了更限制性的補充語法,進一步限制了可接受的token序列。通常,如果“P不覆蓋N”,則早期錯誤規(guī)則將定義錯誤條件,其中P是解析節(jié)點(廣義產生式的實例),N是補充語法的非終結符。這里,用N作為目標符號再次解析由P匹配的token序列。(如果N采用語法參數,則將它們設置為與最初解析P時使用的值相同。)當沒有更多token時,如果無法將token序列解析為N的單個實例,則會發(fā)生錯誤。隨后,算法使用短語“被P覆蓋的N”的短語訪問解析結果。這將始終是一個解析節(jié)點(N實例,對于給定的P是唯一的),因為任何解析失敗都會被早期錯誤規(guī)則檢測到。

5.1.5 文法標記法

詞法,正則表達式和數值型字符串文法的終結符,無論是在文法的產生式還是貫穿本規(guī)范的所有文本直接給出的終結符,都用等寬 (fixed width)字體顯示。這些都會以書面形式完整的出現在腳本中。所有以這種方式指定的終結符字符,可以理解為基本拉丁范圍的Unicode字符,不是任何其他類似的 Unicode 范圍字符。

非終結符以斜體表示。一個非終結符(也叫產生式)的定義由非終結符名稱和其后定義的一個或多個冒號給出。(冒號的數量表示產生式所屬的文法。)非終結符的右側有一個或多個替代子緊跟在下一行。 例如,語法定義:

WhileStatement:
   while (Expression) Statement

表示這個非終結符 WhileStatement 代表token while,其后跟左括號token,其后跟 Expression,其后跟右括號token,其后跟 Statement。這里出現的 ExpressionStatement 本身是非終結符。另一個例子,語法定義:

ArgumentList :
    AssignmentExpression
    ArgumentList , AssignmentExpression

表示這個 ArgumentList 可以代表一個 AssignmentExpression,或 ArgumentList,其后跟一個逗號,其后跟一個 AssignmentExpression。這個 ArgumentList 的定義是遞歸的,也就是說,它定義它自身。其結果是,一個 ArgumentList 可能包含用逗號隔開的任意正數個參數,每個參數表達式是一個 AssignmentExpression。這樣,非終結符共用了遞歸的定義。

終結符或非終結符可能會出現后綴下標“ opt ”,表示它是可選符號。實際上包含可選符號的替代子包含兩個右邊,一個是省略可選元素的,另一個是包含可選元素的。這意味著:

VariableDeclaration :
   BindingIdentifier Initialiseropt

是以下的一種縮寫:

VariableDeclaration :
   BindingIdentifier
   BingingIdentifier Initialiser

并且:

IterationStatement :
   for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

是以下的一種縮寫:

IterationStatement :
   for ( LexicalDeclaration ; Expressionopt ) Statement
   for ( LexicalDeclaration Expression ; Expressionopt ) Statement

是以下的一種縮寫:

IterationStatement :
   for ( LexicalDeclaration ; ) Statement
   for ( LexicalDeclaration ; Expression ) Statement
   for ( LexicalDeclaration Expression ; ) Statement
   for ( LexicalDeclaration Expression ; Expression ) Statement

因此,在這個例子中,非終結符 IterationStatement 實際上有4個右側變體。

產生式可以用下標注釋"[parameters]"的形式進行參數化,該形式可以作為產生式定義的非終端符號的后綴出現。"parameters"可以是單個名稱,也可以是逗號分隔的名稱列表。一個參數化產生式是定義參數名稱的所有組合的一組產生式的縮寫,后面跟下劃線,附加到參數化的非終端符號。這意味著:

StatementList [Return] :
   ReturnStatement
   ExpressionStatement

是以下的一種方便的縮寫:

StatementList :
   ReturnStatement
   ExpressionStatement
StatementList_Return :
   ReturnStatement
   ExpressionStatement

然后:

StatementList [Return, In] :
   ReturnStatement
   ExpressionStatement

是以下的一種縮寫:

StatementList :
   ReturnStatement
   ExpressionStatement
StatementList_Return :
   ReturnStatement
   ExpressionStatement
StatementList_In :
   ReturnStatement
   ExpressionStatement

StatementList_Return_In :
   ReturnStatement
   ExpressionStatement

多個參數生成了組合數量的產生式,但并非所有的產生式都必須在完整的語法中引用。

對產生式右側的非終結符的引用也可以被參數化。例如:

StatementList :
   ReturnStatement
   ExpressionStatement [+In]

相當于:

StatementList :
   ReturnStatement
   ExpressionStatement_In

以及:

StatementList :
   ReturnStatement
   ExpressionStatement [~In]

相當于:

StatementList :
   ReturnStatement
   ExpressionStatement

非終結符引用可以同時具有參數列表和“opt”后綴。例如:

VariableDeclaration :
   BindingIdentifier Initializer [+In] opt

是以下的一種縮寫:

VariableDeclaration :
   BindingIdentifier
   BindingIdentifier Initializer_In

在右側非終結符引用的參數名前加上“?”前綴使該參數值取決于參考當前產生式的左側符號的參數名稱。例如:

VariableDeclaration [In] :
   BindingIdentifier Initializer [?In]

是以下的一種縮寫:

VariableDeclaration :
   BindingIdentifier Initializer
VariableDeclaration_In :
   BindingIdentifier Initializer_In

如果右側的替代方案是以“[+parameter]”為前綴,則只有在引用產生式的非終結符號時使用了該命名參數,該選項才可用。如果右邊的替代方案以“[~parameter]”作為前綴,則只有在引用產生式的非終結符號時不使用該命名參數,該選項才可用。 這意味著:

StatementList [Return] :
   [+Return] ReturnStatement
   ExpressionStatement

是以下的一種縮寫:

StatementList :
   ExpressionStatement
StatementList_Return :
   ReturnStatement
   ExpressionStatement

以及:

StatementList [Return] :
   [~Return] ReturnStatement
   ExpressionStatement

是以下的一種縮寫:

StatementList :
   ReturnStatement
   ExpressionStatement
StatementList_Return :
   ExpressionStatement

如果文法定義的冒號后面出現文字“one of”,那么其后一行或多行出現的每個終結符都是一個選擇定義。例如,ECMAScript包含的詞法文法產生式:

NonZeroDigit :: one of
    1 2 3 4 5 6 7 8 9

這只是下面寫法的一種縮寫:

NonZeroDigit ::
    1
    2
    3
    4
    5
    6
    7
    8
    9

如果產生式的右側出現“[empty]”,它表明,產生式的右側不包含終結符或非終結符。

如果產生式的右側出現“[lookahead ? set]”,它表明,給定 set 的成員不得成為產生式緊隨其后的 token。這個 set 可以寫成一個大括號括起來的由逗號分隔的一個或兩個元素終結符序列的列表。為方便起見,set 也可以寫成一個非終結符,在這種情況下,它代表了這個非終結符 set 可擴展所有終結符。如果 set 由單個終結符組成,則可以使用短語“[lookahead ≠ set]”。例如,給出定義:

DecimalDigit :: one of
    0 1 2 3 4 5 6 7 8 9
DecimalDigits ::
    DecimalDigit

DecimalDigits DecimalDigit

定義

LookaheadExample ::
    n [lookahead ? {1,3,4,5,7,9}] DecimalDigits
    DecimalDigit [lookahead ? DecimalDigit]

能匹配字母 n 后跟隨由偶數起始的一個或多個十進制數字,或一個十進制數字后面跟隨一個非十進制數字。

類似地,如果短語“[lookahead ? set]”出現在產生式的右側,則它指示只有在緊接著的輸入 token 序列是給 set 的成員時才可以使用產生式。如果 set 由單個終結符組成,則可以使用短語“[lookahead = terminal]”。

如果產生式的右側出現“[no LineTerminator here]”,那么它表示此產生式是個受限的產生式:如果 LineTerminator 在輸入流的指定位置出現,那么此產生式將不會被適用。例如,產生式:

ThrowStatement :
    throw [no LineTerminator here] Expression ;

表示如果程序中 throw token 和 Expression 之間的出現 LineTerminator,那么不得使用此產生式。

LineTerminator 除了禁止出現在受限的產生式,可以在輸入元素流的任何兩個 tokens 之間出現任意次數,而不會影響程序的語法驗證。

當一個詞法文法產生式或數字字符串文法中出現多字符 token,它表示此字符序列將注冊一個 token。

使用詞組“but not“可以指定某些不允許在產生式右側的擴展,它說明排除這個擴展。例如,產生式:

Identifier ::
    IdentifierName but not
ReservedWorld

此非終結符 Identifier 可以由可替換成 IdentifierName 的字符序列替換,相同的字符序列不能替換 ReservedWord。

最后,對于實際上不可能列出全部可變元的少量非終結符,我們用普通字體寫出描述性的短語來描述它們:

SourceCharacter ::
    any Unicode code point

5.2 算法約定

此規(guī)范通常使用帶編號的列表來指定算法的步驟。這些算法是用來精確地指定 ECMAScript 語言結構所需的語義。該算法無意暗示任何具體實現使用的技術。在實踐中,也許可用更有效的算法實現一個給定功能。

算法可以被明確地參數化,在這種情況下,參數的名稱和用法必須作為算法定義的一部分提供。

算法的步驟可細分為有序的子步驟。子步驟被縮進,可以將自身進一步劃分為縮進子步驟。大綱編號約定用于識別分步驟,第一層次的子步驟適用小寫字母標記,第二層次的子步驟使用小寫羅馬數字標記。如果需要超過三個層次,則重復這些規(guī)則,第四層次使用數字標記。例如 :
 1.Top-level step
   a.Substep.
   b.Substep.
     i.Subsubstep.
       1.Subsubsubstep
         a.Subsubsubsubstep
           i.Subsubsubsubsubstep

步驟或子步驟可寫“if”謂詞作為它的子步驟的條件。在這種情況下,當謂詞為真時子步驟才適用。如果一個步驟或子步驟由單詞“else”開始,那么它是一個謂詞,否定前面的同一層級的“if”謂詞。

步驟可以表示其子步驟的迭代應用。

以“Assert:”開始的步驟斷言其算法的不變條件。這樣的斷言可以讓算法中隱含的不變條件變成顯式的。這種斷言不會添加額外的語義要求,實現沒有一定去檢查的必要性。它們只是用來讓算法更清晰。

算法步驟可以使用 “l(fā)et x be someValue” 的形式聲明任何值的命名別名。這些別名類似于引用,因為 xsomeValue 都引用相同的底層數據,對二者的修改都是可見的。想要避免這種引用行為的算法步驟應該明確地復制右側的副本:“讓 x 成為 someValue 的副本” 創(chuàng)建 someValue 的淺拷貝。

聲明之后,可以在任何后續(xù)步驟中引用別名,并且不能從別名聲明之前的步驟中引用別名。別名可以使用“設置 x to someOtherValue”的形式進行修改。

5.2.1 抽象操作

為了便于在本說明書的多個部分中使用,一些算法(稱為抽象操作)以參數化的函數形式命名和寫入,以便它們可以從其他算法中通過名稱引用。抽象操作通常使用諸如 操作名(arg1arg2)之類的功能應用程序樣式進行引用。一些抽象操作被當作類化規(guī)范抽象的多態(tài)分派方法。此類方法抽象操作通常使用方法應用程序樣式如someValue。操作名(arg1,arg2)。

5.2.2 語法導向的操作

語法導向的操作是一個命名的操作,它的定義由算法組成,每個算法都與來自ECMAScript語法中的一個或多個結果相關聯。具有多個替代定義的結果通常對于每個替代都有不同的算法。當一個算法與一個文法產生式相關聯時,它可以引用產生式替換的終結符和非終結符,就好像它們是算法的參數一樣。當以這種方式使用時,非終結符指的是在解析源文本時匹配的實際替代定義。

當算法與結果替代相關聯時,替代顯示時沒有任何“[]”語法注釋。這種注釋應該只影響替代方案的句法識別,而不影響替代方案的相關語義。

使用以下算法中的步驟1、3和4中的約定,使用解析節(jié)點和可選的其他參數調用語法導向的操作:

1.讓 *status *成為執(zhí)行非終結符的語法導向操作的結果。
2.讓 someParseNode 成為一些原文本的解析。
3.執(zhí)行 someParseNode 的語法導向操作。
4.以 "value" 為參數執(zhí)行 someParseNode 的語法導向操作。

除非另有明確說明,否則所有鏈產生式都對可能應用于該產品的左側非終結符的每個操作具有隱式定義。隱式定義簡單地將相同參數的相同操作(如果有的話)應用到鏈產生式的唯一右手側非終結符,然后返回結果。例如,假設一些算法有一個步驟的形式是:“返回對 Block 的評估結果”,并且有一個產生式:

Block:
    { Statement }

但是評估操作并不將算法與該產生式關聯。在這種情況下,評估操作隱含地包括形式的關聯:
運行時語義: Evaluation

Block: { Statement }
  1.返回對 StatementList 的評估結果。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容