摘要:除非在本規范中其它指定的文法產生式可選部分隱式地包含一個叫做的接收一個值為包含相關產生式的文法的終結符或者非終結符的參數靜態語義規則的定義。
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)
??必須在運行時被調用的指定語義的算法就叫運行時語義。運行時語義通過抽象操作或者指定語法操作來定義。這樣的算法必須返回一個完成記錄。
??完成類型是一個記錄,用于解釋某些執行非外部控制轉移語句(例如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)完成。
??描述拋出一個異常的算法步驟,例如:
1. Throw a TypeError exception.
??意思就是:
1. Return Completion{[[Type]]: throw, [[Value]]: a newly created TypeError object, [[Target]]: empty}.
??算法步驟說明或者等同于:
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.
??上下文無關文法不能足夠好的去表達所有定義的規則,不管是一個輸入元素的流形成的一個合法的將被解析的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)計算從x到xN的最小值。數學函數max(x1, x2, ..., xN)計算從x到xN的最大值。這些數學函數的域(譯注:即定義域和值域)以及范圍包括+∞和-∞。
??符號“x modulo y”(譯注:即x模y)(y必須是有限的且是非0的)計算出一個值k,它的符號與y一致(或者是0),這樣的k滿足abs(k) < abs(y),以及能找到某個整數y,使得x-k = q * y。
The mathematical function floor(x) produces the largest integer (closest to positive infinity) that is not larger than x.
??
6 ECMAScript數據類型和值(ECMAScript Data Types and Values)注意 floor(x) = x-(x modulo 1). (譯注:即模運算是向0方向舍入)
??本規范的算法操作的值每一個都有其相應的類型。最可能的值類型恰恰是那些定義在這個條款中的類型。類型又進一步分為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類型代表一個擁有兩個值的邏輯的實體,它們被稱為true和false。
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中的某一個:
Specification Name | [[Description]] | Value and Purpose |
---|---|---|
@@hasInstance | "Symbol.hasInstance" | 一個方法,決定一個構造函數對象是否能將一個對象識別為它的實例。由instance操作的語義來調用。 |
@@isConcatSpreadable | "Symbol.isConcatSpreadable" | 一個Boolean值,如果為true,代表一個對象對于Array.prototype.concat應該被壓成扁平的再加入進去。(譯注:比如a.concat一個元素,如果這個元素為數組,會把這個數組的元素挨個push到a后面,這個時候這個元素的@@isConcatSpreadable就為true,如果這個元素是一個對象,那么就把這個對象當成一個整體push到a后面,這個時候這個元素的@@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的對象里屬性不應該包含這些屬性。) |
??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值相關聯。
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值相關聯。
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中定義的默認值:
Attribute Name | Default Value |
---|---|
[[Value]] | undefined |
[[Get]] | undefined |
[[Set]] | undefined |
[[Writable]] | false |
[[Enumerable]] | false |
[[Configurable]] | false |
??在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)。
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]]內置方法的函數對象。
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,除非:
P是一個不可配置的可寫的自身數據屬性。一個不可配置的可寫數據屬性能被改變為一個不可配置的不可寫的數據屬性。
所有在訪問器中的屬性都是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中列出。
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 |
T
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。 轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/84689.html 相關文章
發表評論0條評論xiaokai男|高級講師TA的文章閱讀更多
閱讀需要支付1元查看
|