【譯】ECMAScript文件—序言及1-6章(下)

ne_smalltown發表於2017-08-05

5.2 演算法約定(Algorithm Conventions)

  規範常常使用一個帶編號的列表來顯示演算法中的步驟。這個小演算法被用作準確地表達ECMAScript語言構造需要的語義。這些演算法並不是打算暗示任何具體實現的使用。事實上,這裡也許有更高效的演算法去實現指定的特性。

  演算法也許被顯式的引數化,在這些案例中引數的名稱和用法必須作為演算法定義的一部分提高。

  演算法步驟也許被細分成多個連續的子步驟。子步驟需要用縮排表示,並且也許會進一步被劃分成更小的縮排的子步驟。大綱編號約定被用作標識有小寫字母字元標籤的一級子步驟以及有小寫羅馬數字標籤的二級子步驟。如果超過步驟3級,那麼這些規則從第四級開始用數字標籤進行重複。例如:

1.Top-level step
    a.Substep.
    b.Substep.
        i.Subsubstep.
            1.Subsubsubstep
                a.Subsubsubsubstep
                    i.Subsubsubsubsubstep

  一個步驟或者子步驟也許會使用“if”去斷言它的子步驟的條件。在這樣的案例中,這些子步驟只能適用於“if”斷言為true的情況。如果一個步驟或者子步驟以單詞“else”開始,那麼表示這是之前的“if”斷言的同一級的否定斷言。

  一個步驟也許會指定它的子步驟的迭代程式。

  一個以“Assert:”開頭的步驟斷言一個它的演算法裡不變的條件。這樣的斷言被用作使演算法不變數顯式地展示,否則它將是隱式的。這樣的斷言不增加額外的語義需求,因此在實現中不需要被檢查。它們被使用只是為了使演算法更清晰。

  對於任意形如“Let x be someValue”的值,演算法步驟也許會宣告命名別名。這些別名即可能通過x也可能通過someValue引用,它們指向同一個潛在的資料,並且修改其中任意一個對另一個都是可見的。那些想避免這樣的類似引用的演算法步驟需要顯式地複製一份右值:即“Let x be a copy of someValue”建立了一個someValue的淺複製。

  一旦宣告完畢,別名也許會在隨後的任意步驟或者子步驟中被引用,但是它們也許不會在最高階步驟中被引用。別名也許會通過形如“Set x to someOtherValue”這樣的形式被修改。

5.2.1 抽象操作(Abstract Operations)

  為了促進它們在本規範的多個地方使用,一些演算法,我們稱之為抽象操作,在引數化的函式形式中中命名和書寫,以便它們能夠在其它演算法中通過名稱來引用。抽象操作通常是被通過一個功能化的應用風格引用,如OperationName(arg1, arg2)。一些抽象操作被當作像類規範裡抽象的多型傳送一樣。這樣的類似類的方法抽象操作通常通過一個方法應用風格被引用,如someValue.OperationName(arg1, arg2)。

5.2.2 特定語法操作(Syntax-Directed Operations)

  一個特定的語法操作是一個具有名稱的操作,它的定義包含了一系列演算法,每個演算法與一個或者多個ECMAScript文法的產生式相關聯。一個有多個可選定義的產生式通常對於每個可選部分都有一個獨立的演算法。當一個演算法與一個文法產生式相關聯的時候,它也許會引用這個產生式可選部分的終結符或者非終結符,就好像它們是這個演算法的引數一樣。當出現這種情況時,非終結符指向實際的原始碼中與之匹配的可選部分的定義。

  當一個演算法與一個產生式的可選部分關聯的時候,這個可選部分通常不會帶上“[ ]” 文法註釋。這樣的註釋只應該影響可選部分的語法識別,不應該對相關的可選部分的語義有影響。
Syntax-directed operations are invoked with a parse node and, optionally, other parameters by using the conventions on steps 1, 3, and 4 in the following algorithm:
  特定語法操作同一個解析節點一起被呼叫,還可以在步驟1,3,4中使用這個約定的其它引數。

1. Let `status` be the result of performing SyntaxDirectedOperation of SomeNonTerminal.

2. Let `someParseNode` be the parse of some source text.

3. Perform SyntaxDirectedOperation of `someParseNode`.

4. Perform SyntaxDirectedOperation of `someParseNode` passing
"value" as the argument.

  除非顯式地指定,否則,所有相關聯的產生式對於每個也許會被應用到這個產生式左值的非終結符的操作都有一個隱式的定義。如果存在的話,這個隱式的定義簡單地再次對同樣的引數運用這個相同的定義,對於這些相關聯的產生式唯一的右值非終結符,隨後返回處理結果。例如,假設一些演算法有如下形式的步驟:“返回被解析的塊的結果(Return the result of evaluating Block)”,並且這裡有一個產生式:
  

Block :
    { StatementList }

  但是解析操作並沒有關聯這個產生式的演算法。那麼在這樣的案例中,解析操作隱式地包含了下面形式的關聯:
執行時語義: 解析(Runtime Semantics: Evaluation)

Block : { StatementList }

  1. Return the result of evaluating StatementList.

5.2.3 執行時語義(Runtime Semantics)

  必須在執行時被呼叫的指定語義的演算法就叫執行時語義。執行時語義通過抽象操作或者指定語法操作來定義。這樣的演算法必須返回一個完成記錄。

5.2.3.1 隱式完成值(Implicit Completion Values)

<h5 align=”center”>表8:完成記錄欄位(Completion Record Fields)</h5>

  完成型別是一個記錄,用於解釋某些執行非外部控制轉移語句(例如break, continue, return, throw)執行時值和控制流的傳播。

  完成型別的值是記錄值,它們的欄位定義在表8中。這樣的值被稱為完成記錄。

Filed Value 含義
[[Type]] normal, break, continue, return, throw其中的一個 完成值的型別
[[Value]] 一個ECMAScript語言值或者空值 產生的值
[[Target]] 任意ECMAScript字串或者空值 指定的控制轉移的目標標籤/元素

  本規範的演算法常常隱式地返回一個[[Type]]值為normal的完成記錄(見表8,譯註:由於很多解釋位於較後的章節,如這個定義就位於第6章,而且比較重要,所有對於某些這樣的情況會把它提到前面來)。除非它是上下文中另外非常明顯的部分,一個返回一個值的演算法語句,那麼這個值將不是一個完成值。例如:
1. Return "Infinity".
  與下面的是同一個含義:
1. Return NormalCompletion("Infinity").

  然而,如果一個“return”語句的值表示式是一個完成記錄構造的字面量,那麼完成記錄的結果將被返回。如果這個值表示式是一個對抽象操作的呼叫,那麼“return”語句簡單地返回這個抽象操作產生的完成記錄。

  抽象操作完成(完成記錄)被用作強調之前計算的完成記錄被返回。完成(Completion)這個抽象操作接收一個引數,即完成記錄(completionRecord),然後執行下面的步驟:

1. Assert: completionRecord is a Completion Record.
2. Return completionRecord as the Completion Record of this abstract operation.

  一個在演算法步驟中沒有值的“return”語句與下面的是同樣的意思:
1. Return NormalCompletion(undefined).

  對於任意的在一個上下文中沒有顯示地需要一個完整的完成記錄值的引用,等價於一個顯式地對完成記錄的[[Value]]欄位的引用,除非完成記錄是一個打斷/中斷(abrupt)完成。

5.2.3.2 丟擲一個異常(Throw an Exception)

  描述丟擲一個異常的演算法步驟,例如:
1. Throw a TypeError exception.

  意思就是:
1. Return Completion{[[Type]]: throw, [[Value]]: a newly created TypeError object, [[Target]]: empty}.

5.2.3.3 如果被打斷則返回(ReturnIfAbrupt)

  演算法步驟說明或者等同於:
1. ReturnIfAbrupt(argument).

  意思就是(譯註:abrupt completion就是上面提到的改變控制流如break之類的語句,除了這些之外的就是普通的Completion Record):

1. If argument is an abrupt completion, return argument.
2. Else if argument is a Completion Record, let argument be argument.[[Value]].

  演算法步驟說明或者等同於:
1. ReturnIfAbrupt(AbstractOperation()).

  意思就是:

1. Let hygienicTemp be AbstractOperation().
2. If hygienicTemp is an abrupt completion, return hygienicTemp.
3. Else if hygienicTemp is a Completion Record, let hygienicTemp be hygienicTemp.[[Value]].

  這裡的hygienicTemp是短暫的(臨時的),並且只在ReturnIfAbrupt有關的步驟中中可見。

  演算法步驟說明或者等同於:
1. Let result be AbstractOperation(ReturnIfAbrupt(argument)).

  意思就是:

1. If argument is an abrupt completion, return argument.
2. If argument is a Completion Record, let argument be argument.[[Value]].
3. Let result be AbstractOperation(argument).

5.2.3.4 如果被打斷則返回 縮寫(ReturnIfAbrupt Shorthands)

  對抽象操作和以?為字首的指定語法操作的呼叫暗示著ReturnIfAbrupt需要被應用到結果的完成記錄中。例如,步驟:
1. ? OperationName().

  等價於下面的步驟:
1. ReturnIfAbrupt(OperationName()).

  相似的,對於程式方法的風格,步驟:
1. ? someValue.OperationName().

  等價於
1. ReturnIfAbrupt(someValue.OperationName()).

  相似的,字首!被用作暗示下列的對於抽象或者指定語法操作的呼叫將不會返回一個打斷的(abrupt)完成值,並且作為結果的完成記錄的[[Value]]欄位應該被用作替換操作的返回值,例如,步驟:
1. Let val be ! OperationName().

  等價於下面的步驟:

1. Let val be OperationName().
2. Assert: val is never an abrupt completion.
3. If val is a Completion Record, set val to val.[[Value]].

  對於執行時語義的指定語法的操作通過在呼叫操作前替換!或者?來利用這個縮寫。
1. Perform ! SyntaxDirectedOperation of NonTerminal.

5.2.4 靜態語義(Static Semantics)

  上下文無關文法不能足夠好的去表達所有定義的規則,不管是一個輸入元素的流形成的一個合法的將被解析的ECMAScript指令碼(Script)還是模組(Module)。在一些情況中,需要額外的規則通過使用ECMAScript演算法約定或者散文要求(prose requirements)來展示。這樣的規則總是與一個文法的產生式相關聯,被稱作產生式的靜態語義。

  靜態語義規則擁有名稱,並且通常用一個演算法來定義。具有名稱的靜態語義規則與文法產生式相關聯,對於每個可採用的具有名稱的靜態語義規則,一個包含多個可選部分定義的產生式通常會對每個可選部分定義一個獨有的演算法。

  除非在本規範中其它指定的文法產生式可選部分隱式地包含一個叫做Contains的接收一個值為包含相關產生式的文法的終結符或者非終結符的symbol引數靜態語義規則的定義。預設的包含定義為:

1. For each child node child of this Parse Node, do
    a. If child is an instance of symbol, return true.
    b. If child is an instance of a nonterminal, then
        i. Let contained be the result of child Contains symbol.
        ii. If contained is true, return true.
2. Return false.

  上面的定義是顯式地重寫了規範的產生式。

  一個特殊的靜態語義規則是早期(提前)錯誤規則(Early Error Rule)。早期錯誤規則定了早期錯誤條件(參見條款16),它們與具體的文法產生式相關聯。大多數早期錯誤規則的解析不是在本規範的演算法中顯式地被呼叫。一個符合規範的實現必須在第一次解析指令碼或者模組之前,驗證所有被用作解析指令碼或者模組的產生式的早期錯誤規則。如果違反了任意的早期錯誤規則,那麼指令碼或者模組就是不合法的,並且不能被解析執行。

5.2.5 數學操作(Mathematical Operations)

  除非其它地方特別註明不包括無限並且不包括負0(為了與正0區分),數學操作,例如加,減,否定(邏輯非),乘,除以及隨後在條款中定義的數學函式應總是被當作是對於數學中所有真實數字計算出來的準確的結果。本規範演算法中的浮點運算包含顯式地的步驟,它們對於處理無窮,有符號的0,以及舍入是必要的。如果一個數學操作或者函式被應用在一個浮點數上,那麼它必須被當作應用到用浮點數表示的具體的數學值;這樣的浮點數必須是有限的,並且如果它是+0或者-0的話,那麼相應的數學值就是簡簡單單的0。

  數學函式abx(x)用來計算x的絕對值,如果x是負數(小於0),那麼結果就是-x,否則結果就是x本身。

  數學函式min(x1, x2, …, xN)計算從xxN的最小值。數學函式max(x1, x2, …, xN)計算從xxN的最大值。這些數學函式的域(譯註:即定義域和值域)以及範圍包括+∞和-∞。

  符號“x modulo y”(譯註:即x模y)(y必須是有限的且是非0的)計算出一個值k,它的符號與y一致(或者是0),這樣的k滿足abs(k) < abs(y),以及能找到某個整數y,使得xk = q * y
The mathematical function floor(x) produces the largest integer (closest to positive infinity) that is not larger than x.
  

注意 floor(x) = x-(x modulo 1). (譯註:即模運算是向0方向舍入)

6 ECMAScript資料型別和值(ECMAScript Data Types and Values)

  本規範的演算法操作的值每一個都有其相應的型別。最可能的值型別恰恰是那些定義在這個條款中的型別。型別又進一步分為ECMAScript語言型別(language types)以及規範型別(specification types)。

  在本規範總,符號“Type(x)”用來作為“the type of x”的簡寫,這裡的“type”指向定義在本條款中的ECMAScript語言以及規範型別。當術語“empty”被使用時,就好像它正在命名一個值,這和說“no value of any type”是相等的(譯註:即任何型別都沒有這個值)。

6.1 ECMAScript語言型別(ECMAScript Language Types)

  一個ECMAScript語言型別對應那些被使用ECMAScript語言的ECMAScript程式設計師直接操作的值。ECMAScript語言型別是Undefined, Null, Boolean, String, Symbol, Number, and Object。一個ECMAScript語言值是一個具有ECMAScript語言型別特徵的值。

6.1.1 Undefined型別(The Undefined Type)

  Undefined型別僅僅只有一個值,被稱為undefined。任何沒有被分配一個值的變數的值就是undefined

6.1.2 Null型別(The Null Type)

  Null型別僅僅只有一個值,被稱為null

6.1.3 Boolean型別(The Boolean Type)

  Boolean型別代表一個擁有兩個值的邏輯的實體,它們被稱為truefalse

6.1.4 String型別(The String Type)

  String型別是所有0或者16bit無符號整數值(“elements”)的有順序的序列的集合,最大的長度是2^53 – 1個元素的長度。String型別通常被用作在一個正在執行的ECMAScript程式上展示文字資料,在這樣的案例中,String中的每個元素都被當作一個UTF-16碼元(code unit)。每個元素都被當作這個序列中的一個佔位。這些位置使用非負整數來進行索引。第一個元素(如果存在的話)在索引(index)0的位置,下一個元素(如果存在的話)在索引1的位置,以此類推。一個字串的長度是它內部的元素(即16-bit值)的個數。空字串的長度為0,因此沒有元素。

  ECMAScript操作解釋String值的地方,每個元素被解釋成單個的UTF-16碼元。然而,ECMAScript不會對這個字串的碼元序列施加任何的限制或者需求,所以當按照UTF-16碼元解釋的時候,它們也許是不合規範的。不解釋字串內容的操作把它們當作沒有任何差別的16-bit無符號整數。函式String.prototype.normalize可以被用來顯式地規範化一個字串值。函式String.prototype.localeCompare內部對字串進行了規範化,但是除此之外的其它操作都沒有隱式地規範化字串。只有那些被顯式地指定用來處理語言或者對語言環境敏感的操作才會產生語言敏感的結果。

注意 這個設計背後的基本原理是保證Strings的實現儘可能是簡單和高效的。如果ECMAScript源文字在規範化的形式C內,那麼字串字面量也應當被認為是規範化的,只要它們不包含任何Unicode轉移序列。

  一些操作把字串內容解釋為UTF-16編碼的Unicode碼元。在這樣的案例中,解釋的過程是:

  • 一個範圍在0到0xD7FF的碼元或者範圍在0xE000到0xFFFF的碼元被解釋成一個相同值的碼點(code point)。
  • 一個兩個碼元的序列,第一個碼元c1在範圍0XD800到0XDBFF,第二個碼元c2在範圍0xDC00到0xDFFF,這樣的稱為代理對,它們被解釋為一個值為(c1 – 0xD800) * 0x400 + (c2 – 0xDC00) + 0x10000的碼點(See 10.1.2)。
  • 一個範圍在0xD800到0xDFFF但是不屬於代理對的碼元,被解釋為一個相同值的碼點。

譯註,如果對於Unicode不是很瞭解的話,推薦閱讀每個JavaScript開發者都該懂的Unicode

6.1.5 Symbol型別(The Symbol Type)

  Symbol型別是所有非字串的也許被用作作為物件的屬性的值的集合。

  每個可能的Symbol值都是唯一的和不可變的。

  每個Symbol值永遠地保持一個與之關聯的叫做[[Description]]的值,它要麼是undefined要麼是一個字串值。

6.1.5.1 著名的Symbol(Well-Known Symbols)

  著名的symbols就是我們說的那些被本規範的演算法顯式地引用的內建Symbol值。它們通常被用作屬性(propertied)的key,這些key的值為規範的演算法提供了一種擴充套件。除非其它地方顯式地說明,著名的symbol的值被所有(realm)共享。

  在本規範內,一個著名的symbol通過形如@@name的形式被引用,這裡的name是表1中的某一個:
<h6 align=”center” >表 1 著名的Symbol</h6>

Specification Name [[Description]] Value and Purpose
@@hasInstance “Symbol.hasInstance” 一個方法,決定一個建構函式物件是否能將一個物件識別為它的例項。由instance操作的語義來呼叫。
@@isConcatSpreadable “Symbol.isConcatSpreadable” 一個Boolean值,如果為true,代表一個物件對於Array.prototype.concat應該被壓成扁平的再加入進去。(譯註:比如a.concat一個元素,如果這個元素為陣列,會把這個陣列的元素挨個pusha後面,這個時候這個元素的@@isConcatSpreadable就為true,如果這個元素是一個物件,那麼就把這個物件當成一個整體pusha後面,這個時候這個元素的@@isConcatSpreadable就為false
@@iterator “Symbol.iterator” 一個方法,返回一個物件預設的迭代器(iterator)。由for-of操作的語義來呼叫。
@@match “Symbol.match” 一個正規表示式方法,匹配正規表示式對應的字串。由 String.prototype.match呼叫。
@@replace “Symbol.replace” 一個正規表示式方法,替換匹配到的字串中的子串。由String.prototype.replace呼叫。
@@search “Symbol.search” 一個正規表示式方法,返回一個字串中匹配這個正規表示式的位置的索引。由String.prototype.search呼叫。
@@species “Symbol.species” 這是一個函式型別的屬性,那些被用來建立派生物件的建構函式就擁有這個屬性。
@@split “Symbol.split” 一個正規表示式方法,在指定的匹配這個正規表示式的地方分割這個字串。
@@toPrimitive “Symbol.toPrimitive” 一個方法,將一個物件轉換為對應的原始值(primitive value)。由ToPrimitive方法呼叫。
@@toStringTag “Symbol.toStringTag” 這是一個String型別的屬性,被用在一個物件在建立時預設的字串描述上。通過內建的Object.prototype.toString方法訪問。
@@unscopables *“Symbol.unscopables”* 這是一個Object型別的屬性,它自身以及繼承來的屬性的名稱是在with環境中對應的物件中被排除了的屬性的名稱。(譯註:即with的物件裡有的屬性,這個@@unscopables的物件裡屬性不應該包含這些屬性。)

6.1.6 Number型別(The Number Type)

  Number型別剛好有18437736874454810627個(即$2^{64}$ – $2^{53}$ + 3)值,表示雙精度64位格式的在IEEE標準中關於二進位制浮點型別運算的IEEE 754-2008規範的值,除了9007199254740990 (即$2^{53}$ – 2)是一個IEEE規範中截然不同的“Not-a-Number”值(譯註:可參考規範中的2.1.35,6.2節等等),被作為一個單獨的NaN值在ECMAScript中展示。(注意NaN由程式表示式NaN產生。)

注意:在一個Number值已經被儲存後,位模式(bit pattern)也許可以通過一個ArrayBuffer或者SharedArrayBuffer觀察到,但是這和Number值的內部表示一樣,不是ECMAScript的實現所必須的。

  這裡有兩種其它的特殊值,叫做正無窮和負無窮。為了簡潔和說明目的,這些值也分別用符號+∞-∞表示。(注意這兩個無窮數由程式表示式+Infinity(或者簡單的Infinity)和-Infinity產生)

  其它的18437736874454810624個值(即,$2^{64}$ – $2^{53}$)被稱作有限數(finite numbers)。其中一半是正數,一半是負數;對於每個有限正數值,這裡都有一個相應量級的負數值。

  注意這裡既有正0也有負0。為了簡潔和說明的目的,這些值也分別用符號+0-0表示。(注意這兩個不同的零數字值由程式表示式+0(或者簡單的0)和-0產生。)

  18437736874454810622(即$2^{64}$ – $2^{53}$ – 2)個有限非0值有下面兩種型別:

18428729675200069632 (that is, 264-254) of them are normalized, having the form
  其中的18428729675200069632(即$2^{64}$ – $2^{54}$)個值是被正規化化/規範化(normalized)了的,它們是下面的形式:

$s × m × 2^e$

  這裡的s是+1或者-1,m是一個小於$2^{53}$但是不小於$2^{52}$的正數,e是一個正數,範圍從-1074到971,前後都包含。

  剩下的9007199254740990(即$2^{53} – 2$)個值是沒有被正規化化的,它們是下面的形式:

$s × m × 2^e$

  這裡的s是+1或者-1,m是一個小於$2^{52}$的正數,e是-1074。

  注意Number型別能表示的所有的正數和負數它們的量級/指數都不超過$2^{53}$。(事實上,整數0有兩種表示,+0-0

  如果是非0的話,一個有限數有一個奇數的尾數那麼它就是奇數,整數m用來表示這個尾數(即上面提到的兩種形式之一)。否則,它就有一個偶數的尾數。

  在本規範中,短語“the Number value for x”裡的x剛好代表一個非0值的真實的數學量(也有可能是如π之類的無理數),也意味著一個Number值按照下面的方式被選擇出來。首先考慮Number型別中所有的有限數的集合,除去-0,加上兩個Number型別無法表示的值,被稱為$2^{1024}$(即1 × $2^{53}$ $2^{1024}$)以及$-2^{1024}$(即-1 × $2^{53}$ $2^{1024}$)。然後選擇這個集合中離x最近的元素。如果有兩個值一樣接近,那麼選擇有偶數尾數的那一個。處於為此目的考慮,兩個額外的值$2^{1024}$和$-2^{1024}$被認為是擁有相同的偶數尾數。最後,如果選擇的是$2^{1024}$,用+∞替換它。如果選擇的是$-2^{1024}$,用-∞替換它。如果選擇的是+0,只在x小於0時才用-0替換它。除了上面提到的這些,任意其它的選擇值是不會發生變化的。最後的結果就是x的Number值。(這樣就能剛好產生與IEEE 754-2008的“round to nearest, ties to even”行為模式相對應的值。)

  一些ECMAScript操作符僅僅處理指定範圍的整數,例如前後都包含的$-2^{31}$到$2^{31} – 1$。或者是0到$2^{16} – 1$的範圍。這些操作符接收任意Number型別的值,但是首先會將它們轉換成像上面提到的這些範圍內的值。可以參考7.1節的數字轉換操作。

6.1.7 Object型別(The Object Type)

  一個物件邏輯上是一個屬性的集合。每個屬性要麼是一個資料屬性(data property),要麼是一個訪問器屬性(accessor property):

  • 一個資料屬性關聯一個ECMAScript語言值的key值以及一個Boolean屬性的集合。
  • 一個訪問器屬性關聯一個或兩個訪問器函式的key值,一級一個Boolean屬性的集合。訪問器函式被用來儲存或者檢索與這個屬性相關的ECMAScript語言值

  屬性是用key值來識別的。一個屬性的key值要麼是一個ECMAScript String值,要麼是一個Symbol值。所有的String和Symbol值,包括空字串,都是合法的屬性key值。當一個屬性的key是String值的時候,這個屬性的name是這個屬性的key。

  一個整數索引是一個字串值的屬性key,它是一個規範的數字String(canonical numeric String)(參考7.1.16)。它的數字值要麼是+0,要麼是一個小於等於$2^{53}$-1的正數。一個陣列索引是一個整數索引,它的數字值i的範圍是+0 ≤ i < $2^{32}-1$。(譯註:即Array(2**32)會報錯:Uncaught RangeError: Invalid array length,而Array(2**32 - 1)不會

  屬性的key被用來訪問屬性以及它們的值。這裡有兩種對屬性的訪問:get和set。分別對應值的檢索和賦值。通過get和set來進行屬性訪問既包括直接屬於自己的屬性,也包括通過屬性繼承關係從其它相關物件繼承來的屬性。繼承的屬性也可能是另一個物件的自身屬性或者繼承來的屬性。一個物件的每個自身屬性必須有一個key值來區分它和這個物件的其它的自身屬性。

  所有的物件都是邏輯上的屬性集合,但是物件卻有多種形式用來區分訪問以及變化它們的屬性的語義。普通的物件是物件的最常見形式,擁有預設的物件語義。一個外來物件是這樣的物件形式,它的屬性語義與預設語義的各個方面都有區別。

6.1.7.1 Property Attributes

  本規範中的屬性(Attributes)被用作定義和解釋物件屬性(Object properties)的狀態。一個資料屬性(data property)與表2中列出的屬性的key值相關聯。

<h6 align=”center”>表2 Attributes of a Data Property</h6>

Attribute Name Value Domain Description
[[Value]] 任意的ECMAScript語言型別 訪問屬性時被檢索到的值
[[Writable]] Boolean 如果為false,任何嘗試通過[[Set]]去改變這個屬性的[[Value]]屬性的ECMAScript程式碼都不會成功。
[[Enumerable]] Boolean 如果為true,這個屬性被for-in列舉時將會是可列舉的(參考13.7.5)。否則,這個屬性就是不可列舉的。
[[Configurable]] Boolean 如果為false,任何嘗試刪除這個屬性,把這個屬性改為訪問器屬性,或者改變它的除了[[Value]]之外的屬性,或者改變它的[[Writable]]為false的操作都會失敗。

  一個訪問器屬性accessor property)與表3中列出的屬性的key值相關聯。

<h6 align=”center”>表3 Attributes of an Accessor Property</h6>

Attribute Name Value Domain Description
[[Get]] Object Undefined 如果這個值是一個物件,那麼它必須是一個函式物件。在每次訪問這個屬性的時候,這個函式的內建[[Call]]方法(下面的表6中)將會被呼叫,同時會向這個方法傳入一個空的arguments。
[[Set]] Object Undefined 如果這個值是一個物件,那麼它必須是一個函式物件。在每次設定這個屬性的時候,這個函式的內建[[Call]]方法(下面的表6中)將會被呼叫,同時會向這個方法傳入包含所賦的值的arguments,作為這個arguments的唯一引數。[[Set]]內建方法也許會對後續的[[Get]]內建方法呼叫產生的返回值產生影響,但不是必須的。
[[Enumerable]] Boolean 如果為true,這個屬性被for-in列舉時將會是可列舉的(參考13.7.5)。否則,這個屬性就是不可列舉的。
[[Configurable]] Boolean 如果為false,任何嘗試刪除這個屬性,把這個屬性改為資料屬性,或者改變它的其它attributes的操作都會失敗。

  如果一個屬性的attributes的初始值沒有被本規範顯式地指定的時候,那麼使用在表4中定義的預設值:
<h6 align=”center”>表4 Default Attribute Values</h6>

Attribute Name Default Value
[[Value]] undefined
[[Get]] undefined
[[Set]] undefined
[[Writable]] false
[[Enumerable]] false
[[Configurable]] false

6.1.7.2 物件的內建方法和內建槽(Object Internal Methods and Internal Slots)

  在ECMAScript中,物件的實際語義是通過演算法來呼叫內建方法指定的。在ECMAScript引擎中的每個物件都與一系列的定義它的執行時行為的內建方法相關聯。這些內建方法不屬於ECMAScript語言的一部分。通過本規範定義它們的部分僅僅是為了解釋和說明的目的。然而,在ECMAScript具體實現中的每個物件必須表現得像這些內建方法與它關聯了一樣。其中的準確的行為由實現來決定。

  內建方法(Internal method)的名稱是多種多樣的。這意味著當一個常見的內建方法被呼叫的時候,不同的物件值也許會執行不同的演算法。內建方法被呼叫時實際的物件成為這個呼叫的“目標”(“target”)。如果在執行時一個演算法的實現嘗試去使用一個物件不支援的內建方法,一個TypeError將會被丟擲。

  內建槽(Internal slots)對應相關聯物件的內部狀態,被ECMAScript規範中不同的演算法使用。內建槽不是物件的屬性,也不會被繼承。根據規範中具體的內建槽,這樣的內部狀態也許包含任意ECMAScript語言型別的值或者指定的ECMAScript規範型別的值。除非顯式地指定,否則內建槽作為建立一個物件的一部分過程被分配,並且也許不能被動態地新增到物件上。除非顯式地指定,否則一個內建槽的初始值是undefined。本規範內不同的演算法都會建立有內建槽的物件。然而,ECMAScript語言不提供直接的方法去訪問一個物件的內建槽。

  本規範內的內建方法和內建槽使用閉合的雙方括號[[]]來標識。

  下方的表5總結了被規範使用的適用於所有物件的建立或者被ECMAScript程式碼操作的至關重要的內建方法。每個物件對於所有至關重要的演算法都必須有相應的演算法。然而,所有的物件沒有必要對那些方法使用相同的演算法。

  下面的表5中的 “Signature”列以及其它相似的表格描述了每個內建方法的呼叫模式。呼叫模式總是包含一個括起來的描述引數名的列表。如果一個引數名與ECMAScript型別的名字一樣,那麼代表描述的是引數值需要的型別。如果一個內建方法顯式地返回了一個值,它的引數列表隨後就會跟著一個“→”符合,以及返回值的型別。在signature中使用的型別的名字指向在條款6中定義的型別,另外還增加了一些下面的名稱。“any”代表這個值也許是任意的ECMAScript語言值。一個內建方法會隱式地返回一個完成記錄。除了它的引數,一個內建方法還總是會訪問這個方法呼叫的物件的目標(即前面提到的target)。

<h6 align=”center”>表5 Essential Internal Methods</h6>

Internal Method Signature Description
[[GetPrototypeOf]] ( ) → Object Null 確定為這個物件提供繼承的屬性的物件。一個null值代表沒有繼承的屬性。
[[SetPrototypeOf]] (Object Null) → Boolean 將這個物件與提供繼承的屬性的物件相關聯。傳遞null表示沒有繼承的屬性。返回true表示操作成功,返回false表示操作失敗。
[[IsExtensible]] ( ) → Boolean 決定是否允許新增額外的屬性到這個物件上。
[[PreventExtensions]] ( ) → Boolean 控制一個新的屬性是否能加到這個物件上。返回true表示操作成功,返回false表示操作失敗。
[[GetOwnProperty]] (propertyKey) → Undefined Property Descriptor 返回這個物件的一個自身屬性(own property)的屬性描述符,它的key為propertyKey,或者undefined(如果沒有這樣的屬性存在的話)。
[[DefineOwnProperty]] (propertyKey, PropertyDescriptor) → Boolean 建立或者改變自身屬性,它的key為propertyKey,它的狀態為PropertyDescriptor。返回true表示屬性被成功建立/更新,返回false表示屬性不能被建立/更新。
[[HasProperty]] (propertyKey) → Boolean 返回一個Boolean值,代表這個物件是否已經有一個自身的或者繼承的key為propertyKey的屬性。
[[Get]] (propertyKey, Receiver) → any 返回這個物件裡key值為propertyKey的屬性的值。如果任何的ECMAScript程式碼必須被執行來檢索這個屬性值,Receiver就會作為解析程式碼時的this值。
[[Set]] (propertyKey, value, Receiver) → Boolean 設定這個物件中的key為propertyKey的屬性的值為value。如果任何的ECMAScript程式碼必須被執行來檢索這個屬性值,Receiver就會作為解析程式碼時的this值。返回true表示這個屬效能被設定,返回false表示不能被設定。
[[Delete]] (propertyKey) → Boolean 移除這個物件的key值為propertyKey的自身屬性。返回false表示這個屬性沒有被移除,仍然存在。返回true表示已經被移除,不再存在。
[[OwnPropertyKeys]] ( ) → List of propertyKey 返回一個一個List,這個List裡的元素都來自這個物件的自身屬性的key。

  下方的表6總結了也許會被當作函式來呼叫的物件的額外的至關重要的內建方法。一個函式物件是一個支援[[Call]]內建方法的物件。一個構造器(也被稱為建構函式)是一個支援[[Construct]]內建方法的函式物件。
<h6 align=”center”>表6 Additional Essential Internal Methods of Function Objects</h6>

Internal Method Signature Description
[[Call]] (any, a List of any) → any Null 執行這個物件相關聯的程式碼。通過一個函式表示式來呼叫。通過呼叫表示式,傳遞給內建方法的arguments是一個this值以及一個包含傳遞給自己函式的引數的列表。實現這個內建方法的物件被稱為可呼叫的(callable)。
[[Construct]] (a List of any, Object) → Object Null 通過new或者super操作符建立一個物件。傳遞給這個內建方法的第一個引數是一個包含操作符的引數的列表。第二個引數是new操作符初始化時應用的物件。實現這個內建方法的物件被稱為建構函式(constructors)。一個函式物件不一定是建構函式,這樣的非建構函式的函式物件沒有[[Construct]]內建方法。(譯註:比如new Window()會丟擲Uncaught TypeError: Illegal constructor)

  這些普通物件的至關重要的內建方法的語義和標準的外來物件在條款9中指出。如果一個外來物件的任何內建方法的使用不被實現所支援,那麼嘗試使用這個用法時必須丟擲一個TypeError異常。

6.1.7.3 至關重要的內建方法的不變數(Invariants of the Essential Internal Methods)

  ECMAScript引擎中的物件的內建方法必須符合下方指定的不變數列表。普通的ECMAScript物件以及本規範中標準的外來物件維護這些不變數。ECMAScript代理(Proxy)物件通過對[[ProxyHandler]]物件被呼叫的結果的執行時檢查來維護這些不變數。

  任何提供外來物件的實現也必須維護這些物件的不變數。違反這些不變數也許會造成ECMAScript程式碼出現不可預測的行為以及發生安全問題。然而,一個實現對於違反不變數的行為在記憶體安全問題上絕對不能妥協。

  一個實現必須不允許這些不變數在任何例如提供實現了至關重要的內建方法的功能但是沒有執行它們的不變數的可選介面的行為中被規避。

定義:

  • 一個內建方法的target是一個物件,這個物件的對應的內建方法會被呼叫。
  • 如果一個target被觀察到它的[[IsExtensible]]內建方法返回false或者[[PreventExtensions]]返回true,那麼它是不可擴充套件的。
  • 一個不存在的屬性是指那些在不可擴充套件的target的自身屬性上不存在的屬性。
  • 所有引用SameValue(譯註:即判斷兩個值是否相等)的地方都根據SameValue演算法。

[[GetPrototypeOf]] ( )

  • 返回值的型別必須是Object或者Null。
  • 如果target是不可擴充套件的,並且[[GetPrototypeOf]]返回了一個值v,那麼任何將來的對[[GetPrototypeOf]]的呼叫都應該返回v的SameValue。

注意1: 一個物件的原型鏈的長度應該是有限的(也就是說,從任意物件開始,遞迴地對結果應用[[GetPrototypeOf]]內建方法最終應該得到null)。然而,如果這個原型鏈包含任意的不使用普通物件的[[GetPrototypeOf]]定義的外來物件,那麼作為一個物件的不變數水平,這個要求不是強制的。當訪問物件屬性的時候,這樣的一個環形的原型鏈也許最終會導致無限迴圈。

[[SetPrototypeOf]] (V)

  • 返回值的型別必須是Boolean。
  • 如果target是不可擴充套件的,[[SetPrototypeOf]]必須返回false,除非V是target觀察到的[[GetPrototypeOf]]值的SameValue。

[[IsExtensible]] ( )

  • 返回值的型別必須是Boolean。
  • 如果[[IsExtensible]]返回false,所有將來的在target上的對[[IsExtensible]]的呼叫都必須返回false。

[[PreventExtensions]] ( )

  • 返回值的型別必須是Boolean。
  • 如果[[PreventExtensions]]返回false,所有將來的在target上的對[[IsExtensible]]的呼叫都必須返回false,並且現在開始target被認為是不可擴充套件的。

[[GetOwnProperty]] ( )

  • 返回值的型別必須是Property Descriptor或者Undefined。
  • If the Type of the return value is Property Descriptor, the return value must be a complete property descriptor (see 6.2.5.6).
  • 如果返回值的型別是Property Descriptor,那麼返回值必須是一個完整的property descriptor(參考6.2.5.6)。
  • 如果一個屬性P被描述為一個含有Desc的資料屬性。訪問器 的[[Value]]等於v,訪問器的[[Writable]]以及[[Configurable]]為false,那麼對於訪問器的[[Value]]屬性,必須返回SameValue。將來對這個屬性的[[Value]]屬性的呼叫變成[[GetOwnProperty]] ( P )。
  • 如果P的除了[[Writable]]之外的屬性隨著時間發生了變化或者這個屬性消失了,那麼P的[[Configurable]]屬性必須變成true。
  • 如果[[Writable]]屬性從false變成了true,那麼[[Configurable]]屬性必須變成true。
  • 如果target是不可擴充套件的,並且P是不存在的,那麼所有將來在target上對[[GetOwnProperty]] (P)的呼叫必須把P描述為不存在的(即[[GetOwnProperty]] (P)必須返回undefined)。

注意2: 作為第三個不變數的結論,如果一個屬性被描述為一個資料屬性並且隨著時間它返回不同的值,那麼訪問器的[[Writable]]和[[Configurable]]屬性必須是true,即使沒有機制去改變通過其它內建方法暴露出來的值。

[[DefineOwnProperty]] ( P, Desc)

  • 返回值的型別必須是Boolean。
  • 如果P之前已經被觀察為target的一個不可配置的自身屬性,[[DefineOwnProperty]]必須返回false,除非:
    1. P是一個不可配置的可寫的自身資料屬性。一個不可配置的可寫資料屬效能被改變為一個不可配置的不可寫的資料屬性。
    1. 所有在訪問器中的屬性都是P的屬性的SameValue。
  • 如果target是不可擴充套件的並且P是一個不存在的自身屬性,[[DefineOwnProperty]] (P, Desc)必須返回false。也就是說,一個不可擴充套件的物件不能擴充套件新的屬性。

[[HasProperty]] ( P )

  • 返回值的型別必須是Boolean。
  • 如果P之前被觀察到是target的一個不可配置的資料或者訪問器自身屬性,[[HasProperty]]必須返回true。

[[Get]] (P, Receiver)

  • 如果P之前被觀察到是target的一個value為v的不可配置且不可寫的自身資料屬性,那麼[[Get]]必須返回SameValue。
  • 如果P之前被觀察到是[[Get]]屬性是undefined的target的一個不可配置的自身訪問器屬性,那麼[[Get]]操作必須返回undefined。

[[Set]] ( P, V, Receiver)

  • 返回值的型別必須是Boolean。
  • 如果P之前被觀察到是target的一個value為v的不可配置且不可寫的自身資料屬性,那麼[[Set]]必須返回false,除非V是P的[[Value]]屬性的SameValue。
  • 如果P之前被觀察到[[Set]]屬性是undefined 的target的是一個不可配置的自身訪問器屬性,那麼[[Set]]操作必須返回undefined。

[[Delete]] ( P )

  • 返回值的型別必須是Boolean。
  • 如果P之前被觀察到是target的一個不可配置的自身資料屬性或者訪問器屬性,[[Delete]]必須返回false。

[[OwnPropertyKeys]] ( )

  • 返回值必須是一個List。
  • 返回的List中的每個元素的型別要麼是String,要麼是Symbol。
  • 返回的List必須至少包含之前觀察到的所有的不可配置的自身屬性。
  • 如果這個物件是不可擴充套件的,那麼返回的List必須只能包含這個物件的所有通過[[GetOwnProperty]]觀察到的自身屬性的key。

[[Construct]] ( )

  • 返回值的型別必須是Object。

6.1.7.4 著名的內部物件(Well-Known Intrinsic Objects)

  著名的內部函式是那些被本規範的演算法顯式地引用的內建物件,在這些函式中通常擁有基於特定域(realm-specific)下的特性。除非另有說明,否則每個內部物件在每個中都實際對應一個相似物件的集合。

  在本規範中,一個像%name%這樣的引用就表示關聯到當前域的內部物件的對應的name。當前域的確定以及它的內部情況在8.3節中描述。著名/常見的內部物件在下面的表7中列出。
<h6 align=”center”>表7 Well-known Intrinsic Objects</h6>

Intrinsic Name Global Name ECMAScript Language Association
%Array% Array Array建構函式(參考22.1.1
%ArrayBuffer% ArrayBuffer ArrayBuffer建構函式(參考24.1.2
%ArrayBufferPrototype% ArrayBuffer.prototype %ArrayBuffer%的prototype資料屬性的初始值
%ArrayIteratorPrototype% Array迭代器的prototype物件(參考22.1.5
%ArrayPrototype% Array.prototype %Array%的prototype資料屬性的初始值(參考22.1.3
%ArrayProto_values% Array.prototype.values %ArrayPrototype%的prototype資料屬性的初始值(參考22.1.3.30
%AsyncFunction% 非同步的函式物件(async function )的構造器(參考25.5.1
%AsyncFunctionPrototype% %AsyncFunction%的prototype資料屬性的初始值
%Atomics% Atomics Atomic物件(參考24.4
%Boolean% Boolean Boolean建構函式(參考19.3.1
%BooleanPrototype% Boolean.prototype %Boolean%的prototype資料屬性的初始值(參考19.3.3
%DataView% DataView DataView建構函式(參考24.3.2
%DataViewPrototype% DataView.prototype %DataView%的prototype資料屬性的初始值
%Date% Date Date建構函式(參考20.3.2
%DatePrototype% Date.prototype %Date%的prototype資料屬性的初始值
%decodeURI% decodeURI decodeURI函式(參考18.2.6.2
%decodeURIComponent% decodeURIComponent decodeURIComponent函式(參考18.2.6.3
%encodeURI% encodeURI encodeURI函式(參考18.2.6.4
%encodeURIComponent% encodeURIComponent encodeURIComponent函式(參考18.2.6.5
%Error% Error Error建構函式(參考19.5.1
%ErrorPrototype% Error.prototype %DataView%的prototype資料屬性的初始值
%eval% eval eval函式(參考18.2.1
%EvalError% EvalError EvalError建構函式(參考19.5.5.1
%EvalErrorPrototype% EvalError.prototype %EvalError%的prototype資料屬性的初始值
%Float32Array% Float32Array Float32Array建構函式(參考22.2
%Float32ArrayPrototype% Float32Array.prototype %Float32Array%的prototype資料屬性的初始值
%Float64Array% Float64Array Float64Array建構函式(參考22.2
%Float64ArrayPrototype% Float64Array.prototype %Float64Array%的prototype資料屬性的初始值
%Function% Function Function建構函式(參考19.2.1
%FunctionPrototype% Function.prototype %Function%的prototype資料屬性的初始值
%Generator% %Generator%的prototype資料屬性的初始值
%GeneratorFunction% generator物件的建構函式(參考25.2.1
%GeneratorPrototype% %Generator%的prototype資料屬性的初始值
%Int8Array% Int8Array Int8Array建構函式(參考22.2
%Int8ArrayPrototype% Int8Array.prototype %Int8Array%的prototype資料屬性的初始值
%Int16Array% Int16Array Int16Array建構函式(參考22.2
%Int16ArrayPrototype% Int16Array.prototype %Int16Array%的prototype資料屬性的初始值
%Int32Array% Int32Array Int32Array建構函式(參考22.2
%Int32ArrayPrototype% Int32Array.prototype %Int32Array%的prototype資料屬性的初始值
%isFinite% isFinite isFinite函式(參考18.2.2
%isNaN% isNaN isNaN函式(參考18.2.3
%IteratorPrototype% 一個物件,所有的內建物件的迭代器物件間接地都從這個物件繼承而來。
%JSON% JSON JSON物件(參考24.5
%Map% Map Map建構函式(參考23.1.1
%MapIteratorPrototype% Map迭代器物件的原型(參考23.1.5
%MapPrototype% Map.prototype %Map%的prototype資料屬性的初始值
%Math% Math JSON物件(參考20.2
%Number% Number Number建構函式(參考20.1.1
%NumberPrototype% Number.prototype %Number%的prototype資料屬性的初始值
%Object% Object Object建構函式(參考19.1.1
%ObjectPrototype% Object.prototype %Object%的prototype資料屬性的初始值(參考19.1.3
%ObjProto_toString% Object.prototype.toString %Object%的toString資料屬性的初始值(參考19.1.3.6
%ObjProto_valueOf% Object.prototype.valueOf %Object%的valueOf資料屬性的初始值(參考19.1.3.7
%parseFloat% parseFloat parseFloat函式(參考18.2.4
%parseInt% parseInt parseInt函式(參考18.2.5
%Promise% Promise Promise建構函式(參考25.4.3
%PromisePrototype% Promise.prototype %Promise%的prototype資料屬性的初始值
%Proxy% Proxy Proxy建構函式(參考26.2.1
%RangeError% RangeError RangeError建構函式(參考19.5.2.2
%RangeErrorPrototype% RangeError.prototype %RangeError%的prototype資料屬性的初始值
%ReferenceError% ReferenceError ReferenceError建構函式(參考19.5.5.3
%ReferenceErrorPrototype% ReferenceError.prototype %ReferenceError%的prototype資料屬性的初始值
%Reflect% Reflect Reflect物件(參考26.1
%RegExp% RegExp RegExp建構函式(參考21.2.3
%RegExpPrototype% RegExp.prototype %RegExp%的prototype資料屬性的初始值
%Set% Set Set建構函式(參考23.2.1
%SetIteratorPrototype% Set迭代器物件的prototype(參考23.2.5
%SetPrototype% Set.prototype %Set%的prototype資料屬性的初始值
%SharedArrayBuffer% SharedArrayBuffer SharedArrayBuffer建構函式(參考24.2.2
%SharedArrayBufferPrototype% SharedArrayBuffer.prototype %SharedArrayBuffer%的prototype資料屬性的初始值
%String% String String建構函式(參考21.1.1
%StringIteratorPrototype% String迭代器物件的prototype(參考21.1.5
%StringPrototype% String.prototype %String%的prototype資料屬性的初始值
%Symbol% Symbol Symbol建構函式(參考19.4.1
%SymbolPrototype% Symbol.prototype %Symbol%的prototype資料屬性的初始值(參考19.4.3
%SyntaxError% SyntaxError SyntaxError建構函式(參考19.5.5.4
%SyntaxErrorPrototype% SyntaxError.prototype %SyntaxError%的prototype資料屬性的初始值
%ThrowTypeError% 一個函式物件,無條件的丟擲一個%TypeError%的例項
%TypedArray% 所有的typed Array建構函式的父類(參考22.2.1
%TypedArrayPrototype% %TypedArray%的prototype資料屬性的初始值
%TypeError% TypeError TypeError建構函式(參考19.5.5.5
%TypeErrorPrototype% TypeError.prototype %TypeError%的prototype資料屬性的初始值
%Uint8Array% Uint8Array Uint8Array建構函式(參考22.2
%Uint8ArrayPrototype% Uint8Array.prototype %Uint8Array%的prototype資料屬性的初始值
%Uint8ClampedArray% Uint8ClampedArray Uint8ClampedArray建構函式(參考22.2
%Uint8ClampedArrayPrototype% Uint8ClampedArray.prototype %Uint8ClampedArray%的prototype資料屬性的初始值
%Uint16Array% Uint16Array Uint16Array建構函式(參考22.2
%Uint16ArrayPrototype% Uint16Array.prototype %Uint16Array%的prototype資料屬性的初始值
%Uint32Array% Uint32Array Uint32Array建構函式(參考22.2
%Uint32ArrayPrototype% Uint32Array.prototype %Uint32Array%的prototype資料屬性的初始值
%URIError% URIError URIError建構函式(參考19.5.5.6
%URIErrorPrototype% URIError.prototype %URIError%的prototype資料屬性的初始值
%WeakMap% WeakMap WeakMap建構函式(參考23.3.1
%WeakMapPrototype% WeakMap.prototype %WeakMap%的prototype資料屬性的初始值
%WeakSet% WeakSet WeakSet建構函式(參考23.4.1
%WeakSetPrototype% WeakSet.prototype %WeakSet%的prototype資料屬性的初始值

6.2 ECMAScript規範型別(ECMAScript Specification Types)

譯註:本小節大部分都是演算法,所以只是翻譯一下各小節最前面的文字介紹,即每一小節的後面還有很多相應的演算法,對這些具體演算法有興趣可以自己再研究研究。

  一個規範型別對應那些被用在演算法中去描述ECMAScript語言結構/構造以及ECMAScript語言型別的後設資料。規範型別包括,Reference, List, Completion, Property Descriptor, Lexical Environment, Environment Record以及Data Block。規範型別的值是規範裡才有的,在ECMAScript實現中沒有必要與任何具體的實體相關聯/對應。規範型別的值也許被用來描述ECMAScript表示式解析後的中間結果,但是這樣的值不能被儲存作為ECMAScript語言變數的物件屬性或值的一部分。

6.2.1 List和Record規範型別(The List and Record Specification Types)

  List型別被用來解釋在new表示式中對於argument lists(參考12.3.6)的解析,以及在函式呼叫中,或者在其它需要一個簡單的有序的值的list的演算法的地方。List型別的值是簡單的包含各自list元素的有序序列。這些序列可能是任意的長度。一個list中的元素可以通過0到某個區間內的索引來隨機訪問。為了記數方便,一個類陣列語法可以被用來訪問List的元素。例如,arguments[2]是arguments List中第三個元素的簡寫。

  為了本規範的記法方便,可以用一個字面量語法來表示一個新的List值。例如,« 1, 2 »定義了一個有2個元素的List值,每個元素都被例項化為了一個具體的值。一個新的空的List可以用« »表示。

  Record型別被用來描述在本規範演算法內的資料的聚合。一個Record型別的值包含一個或者多個命名的欄位。每個欄位的值要麼是一個ECMAScript值,要麼是一個用一個關聯Record型別的名稱表示的抽象值。欄位名總是雙方括號閉合的,例如[[Value]]。

  為了本規範的方便,一個類似物件字面量的語法被用來表示一個Record值。例如,{[[Field1]]: 42, [[Field2]]: false, [[Field3]]: empty}定義了一個包含3個欄位的Record值,其中的每一個都被例項化為了一個具體的值。欄位名的順序是不重要的。任何沒有被顯式地列出的欄位都被認為是不存在的。

  在規範的文字和演算法中,點符號也許會被用來指向一個具體的一個Record值的某個特定欄位。例如,如果R是一個在之前的段落中出現的record,那麼R.[[Field2]]代表“R中名稱叫[[Field2]]的欄位”的簡寫。

  常見的使用Record欄位組合模式的地方也許是被命名了的,這個名稱用在一個Record字面量前作為字首,來定義描述的具體的聚合型別。例如: PropertyDescriptor{[[Value]]: 42, [[Writable]]: false, [[Configurable]]: true}。

6.2.2 Set和關係規範型別(The Set and Relation Specification Types)

  Set型別被用來解釋在記憶體模型中無序元素的集合。Set型別的值是簡單的元素的集合,其中沒有任何元素出現超過2次。元素可以從Set中新增或者刪除。不同的Set可以是聯合的(unioned),分割的或者除去的。(譯註:即數學中集合之間的關係,並,交,補等。)

  關係(Realation)型別被用來解釋在Set上的約束。一個關係型別的值是它的的值域中有序對的集合。例如,一個在event上的關係是一個有序的的event對的集合。對於一個關係R以及在R的值域中的兩個值aba R b是有序對(a, b)R的成員的簡寫。(譯註,這些在離散數學中應該都有相應的介紹)

6.2.3 完成記錄規範型別(The Completion Record Specification Type)

  見前面的5.2.3.1。

6.2.4 引用規範型別(The Reference Specification Type)

注意:引用型別被用來解釋像deletetypeof,賦值等操作符以及super關鍵字,以及其它語言特性的行為。例如,賦值操作左邊的運算元應該是一個引用。

  一個引用是一個解析後的名稱或者屬性繫結。一個引用包含3個元件,基礎的值元件(value component),引用的名稱元件(name component),以及Boolean值的是否引用嚴格模式的flag。基礎的值元件要麼是undefined,要麼是一個物件,Boolean,String,Symbol,Number,或者一個環境記錄(Environment Record)。一個undefined的基礎值元件表示這個引用不能被解析為一個繫結。引用的名稱元件是一個String或者Symbol值。

  一個超引用(Super Reference)是一個被用來表示一個用super關鍵字表示的名稱繫結的引用。一個超引用有額外的thisValue元件,它的基礎值元件將永遠不能是一個環境記錄。

6.2.5 屬性描述符規範型別(The Property Descriptor Specification Type)

  屬性描述符型別被用來解釋對物件屬性的操作和物化。屬性描述符的值是Record。每個欄位的名稱是一個屬性名稱,並且它的值是一個在6.1.7.1中相對應的屬性值。此外,任何的欄位都可以被展示或者省略。在本規範內使用的對屬性描述符的record的標籤字面量描述模式名稱為“PropertyDescriptor”。

  屬性描述符的值也許會進一步在基於已存在的某些欄位上依據資料屬性描述符和訪問器屬性描述符來進行分類。一個資料屬性描述符是包含[[Value]]或者[[Writable]]的任意欄位名的型別。一個訪問器屬性描述符包含是[[Get]]或者[[Set]]的任意欄位名的型別。任何一個屬性描述符都包含[[Enumerable]]和[[Configurable]]欄位名。一個屬性描述符的值也許既不是一個資料屬性描述符,也不是一個訪問器屬性描述符。然而,也有可能都是。一個一般的屬性描述符是一個既不是資料屬性描述符也不是訪問器屬性描述符的值。一個完全被填充的屬性描述符是一個包含所有在表2或者表3中相應屬性的欄位的訪問器屬性描述符或者一個資料屬性描述符。

6.2.6 詞法環境和環境記錄規範型別(The Lexical Environment and Environment Record Specification Types)

The Lexical Environment and Environment Record types are used to explain the behaviour of name resolution in nested functions and blocks. These types and the operations upon them are defined in 8.1.
  詞法環境(Lexical Environment)和環境記錄(Environment Record)型別被用來解釋在巢狀的函式和塊中的名稱解析行為。在這些之上的型別和操作定義在8.1中。

6.2.7 Data Blocks

  資料塊規範型別被用來描述一個獨特的且不可變的基於位元組(8bit)數字值序列。一個資料塊值用一個固定的位元組數字來建立,它們的每一個的初始值都為0。

  為了本規範的方便,一個類陣列語法被用來訪問一個資料塊值的自己的位元組。這個符號用一個從0開始的索引的位元組序列整數來表示一個資料塊值。例如,如果db是一個5個位元組的資料塊值,那麼db[2]就能被用來訪問它的第三個位元組。

  一個駐留在記憶體中的資料塊能被多個代理併發地引用,我們特指這樣的叫做共享資料塊。一個共享資料塊有一個沒有地址的(address-free)標識(出於為了平等地測試共享資料塊的值的目的):它並不是掛在任意程式中這個塊對應的虛擬地址上,而是記憶體中的這個代表這個塊的地址。只有當它們包含的地址的集合是相等的,兩個資料塊才是相等的。否則,它們就是不相等的,它們包含的地址的集合的交叉為空。最後,共享資料塊與資料塊是有區別的。
The events form a candidate execution, on which the memory model acts as a filter. Please consult the memory model for full semantics.
  共享資料塊的語義使用記憶體模型中的共享資料塊事件來定義。下方的抽象操作介紹了共享資料塊事件以及在記憶體模型上解析語義和事件語義的介面的行為。事件形成了一個候選執行,記憶體模型扮演了一個過濾器的角色。請檢視記憶體模型來了解更多的語義。

結語

  到這裡就暫時告一段落了,雖然在規範的中段和後段還有很多需要我們去學習的,以後經驗豐富一點再看看能不能繼續翻譯吧。當然如果有人受此啟發願意去翻譯,甚至是翻譯css和html的規範那就更好了,W3C的規範有中文版,但是隻有最前面1章,很久都沒有更新了。

  在最後筆者只是大致的看了一下有沒有特別嚴重的比如排版錯誤之類的,翻譯過程中肯定還存在很多問題,不管是翻譯還是理解,都希望大家能夠多多包涵,也希望大家能夠指出錯誤,共同進步~

相關文章