tsy_77

ecma-262 附录B

tsy_77 · 2017-06-10翻译 · 393阅读 原文链接

Web浏览器的附加ECMAScript特性#

当ECMAScript宿主是Web浏览器时,需要本附件中定义的ECMAScript语言语法和语义。但如果ECMAScript宿主不是网络浏览器,本附件的内容是规范但可选的。

注意

本附件描述了各种遗留特性和基于ECMAScript实现的Web浏览器特性。本附件中指定的所有语言的特征和行为都具有一个或多个不良特征,在不使用遗留特性的时候将从本书中移除。但是,这些特性被大量已有的网页所使用,这也意味着浏览器一定会继续支持它们。本附录中的规范定义了这些遗留特性的可互操作实现的要求。

这些特性不是ECMAScript的核心。开发人员在写新的ECMAScript代码时不应该使用或者假设这些特性时存在的。ECMAScript不鼓励应用这些特性除非这些是浏览器实现的一部分或者需要运行浏览器遇到的遗留代码。

B.1附加语法#

B.1.1数字常量#

11.8.3的语法和语义扩展如下,但是严格模式下这些扩展是不被允许的。

Syntax

数字常量::

十进制常量

[二进制整型常量]

八进制整型常量

传统八进制整型常量

传统八进制整型常量

传统八进制整型常量::

0 八进制数

传统八进制整型常量

八进制数位

二进制整型常量::

0

非零数位 二进制数opt

[非八进制二进制整型常量]

非八进制二进制整型常量::

0 非八进制数位

类似二进制的传统八进制整型常量

非八进制数位

非八进制二进制整型常量

二进制数位

类似二进制的传统八进制整型常量::

0 八进制数位

类似二进制的传统八进制整型常量

八进制数位

非八进制数位::下述之一

8 9

B.1.1.1静态语义#

B.1.2字符串常量#

11.8.4的语法和语义扩展如下,但是此扩展不允许用于严格模式的代码:

语法

转义序列::

字符串转义序列

传统八进制转义序列

十六进制转义序列

Unicode转义序列

传统八进制转义序列::

八进制数位[注意 ∉ 八进制数位]

零到三

八进制数位[注意 ∉ 八进制数位]

四到七

八进制数位

零到三

八进制数位

八进制数位

零到三::0123之一

四到七::4567之一

转义序列的定义在严格模式或解析模板字符时不使用。

B.1.2.1Static Semantics#

B.1.3类似HTML的注释#

11.4的语法和语义扩展如下,但使用目标符号模块解析源代码时不允许使用此扩展模块:

模块:

语法

注释::

多行注释

单行注释

单行HTML开注释

单行HTML闭注释

单行界定注释

多行注释::/* 第一行注释opt

行终止符 多行注释字符opt*/ HTML闭注释opt

第一行注释::

单行界定注释字符

单行HTML闭注释::<!-- 单行注释字符opt

单行HTML开注释::

行终止符序列

HTML闭注释

单行界定注释::/ 单行界定注释字符opt/

HTML闭注释:: 空格序列opt 单行界定注释序列opt-->单行评论字符opt

单行界定注释字符::

单行非星号字符 单行界定注释字符opt* 单行后星号注释字符opt

单行非星号字符::

源字符但是不是* 或者 行终止符

单行后星号注释字符::

单行非前斜杠或星号字符 单行界定注释字符opt* 单行后星号注释字符opt

单行非前斜杠或星号字符::

源字符但是不是/ 或者 * 或者 行终止符

空格序列::

空格 空格序列opt

单行界定注释序列::

单行界定注释 空格序列opt 单行界定注释序列opt类似于包含行终止符代码点的多行注释被认为是一个单行HTML闭注释用于语法的解析的行终止符

B.1.4正则表达式#

21.2.1的语法被修改和扩展如下。语法生成的顺序和上下文信息消除了引入这些改变的歧义。当使用下述语法解析时,只有在以前的选项不匹配时才考虑这些替代方案。

这种替代模式语法和语义只会改变BMP模式的语法和语义。以下语法扩展包括使用[U]参数参数化的产生。但是,当使用目标符号上出现的[U]参数进行解析时,这些扩展都不会更改Unicode模式的语法。

语法

[U]::

[+U]断言[U]

[+U]原子[U]

[+U]原子[U]量词

[~U]可量化断言 量词

[~U]断言

[~U]扩展原子 量词

[~U]扩展原子

断言[U]::

^

$

\b

\B

[+U](?=析取[U])

[+U](?!析取[U])

[~U]可量化断言

可量化断言::

(?=析取)

(?!析取)

扩展原子::

.

\ 原子转义

字符集

(析取)

(?:析取)

无效的量化

扩展表达式字符

无效的量化::

{二进制数}

{二进制数,}

{二进制数,二进制数}

扩展表达式字符::

源字符但是不是^ $ . * + ? ( ) [ |

原子转义[U]::

[+U]二进制转义

[+U]字符转义[U]

[+U]字符集转义

[~U]二进制转义仅当二进制转义的值 <= NcapturingParens

[~U]字符集转义

[~U]字符转义

字符转义[U]::

控制转义

c 控制字母

十六进制转义序列

正则Unicode转义序列[?U]

[~U]传统八进制转义序列

标识转义[?U]

标识转义[U]::

[+U]语法字符

[+U]/

[~U]源字符不包含c

非空类范围[U]::

类原子[?U]

类原子[?U] 非空类范围无破折号[?U]

[+U]类原子[U] - 类原子[U] 类范围[U]

[~U]范围内类原子 - 范围内类原子 类范围

非空类范围无破折号[U]::

类原子[?U]

类原子无破折号[?U] 非空类范围无破折号[?U]

[+U]类原子无破折号[U] - 类原子[U] 类范围[U]

[~U]范围内类原子无破折号 - 范围内类原子类范围

类原子[U]::

-

类原子无破折号[?U]

类原子无破折号[U]::

\ 类转义[?U]

源字符但是不包括 ] 或者 -

范围内类原子::

-

范围内类原子无破折号

范围内类原子无破折号::

\ 类转义

源字符但是不包括 ] 和 -

类转义[U]::

b

[+U]二进制转义

[+U]字符转义[U]

[+U]字符集转义

[+U]-

[~U]二进制转义仅当二进制转义的值 是 0时

[~U]字符集转义

[~U]c类控制字母

[~U]字符转义

类控制字母::

二进制数位_

注意

[+ U]和[〜U]的都出现在左边是用来控制消除歧义的优先级。

B.1.4.1模式语义#

21.2.2的语义扩展如下:

在21.2.2.5中引用“原子::( 析取 )”应被解释为“原子::( 析取)”或“扩展原子::( 析取)”)。

21.2.5包括以下附加评估规则:

使用项::可量化的断言量词和使用项::原子量词但是使用可量化的断言代替原子是一样的。

使用项::可量化的断言量词和使用项::原子量词但是使用扩展原子代替原子是一样的。

使用项::扩展原子和使用项::原子但是使用扩展原子代替原子是一样的。

断言(21.2.2.6)包括以下附加评估规则:

使用断言::可量化断言是通过评估可量化断言来获得Matcher并返回该Matcher来进行评估的。

断言(21.2.2.6)断言 ::(?= 析取)和断言::( ?! 析取)的评估规则也用于可量化断言的使用,但是要用可量化断言替代断言。

原子(21.2.2.8)原子除原子 :: 模式字符之外的评估规则也用于使用扩展原子,但是要使用扩展原子代替原子。还添加了以下评估规则:

使用扩展原子 :: 不合法量词的评估规则如下:

  1. 抛出一个SyntaxError异常。

使用扩展原子 :: 扩展模式字符的评估规则如下:

  1. 让ch成为代表扩展模式字符的字符

  2. 让A成为包含字符ch的单元素CharSet。

  3. 调用CharacterSetMatcher(A, false)并返回它的匹配器结果。

字符转移(21.2.2.10)还包括如下评估规则:

使用字符转义::传统八进制转义序列是通过评估传统八进制转义序列(参见B.1.2)的SV并返回其字符结果来进行评估的。

非空类范围(21.2.2.15)包括以下额外的评估规则:

使用非空类范围::范围内类原子-范围内类原子类范围评估如下:

  1. 评估第一个范围内类原子以获取CharSet A。

  2. 评估第二个范围内类原子以获取CharSet B。

  3. 评估类范围以获取CharSet C。

  4. 调用CharacterRangeOrUnion(A,B),让D成为结果的CharSet。

  5. 返回CharSets D和C的联合。

非空类范围非破折号 (21.2.2.16)包括如下额外的规则:

使用扩展 非空类范围非破折号::范围内类原子非破折号-范围内类原子类范围的评估规则如下:

  1. 评估范围内类原子非破折号以获取CharSet A。

  2. 评估范围内类原子以获取CharSet B。

  3. 评估类范围以获取CharSet C。

  4. 调用CharacterRangeOrUnion(A,B),让D成为结果的CharSet。

  5. 返回CharSets D和C的联合。

类原子 (21.2.2.17)包括如下评估规则:

使用范围内类原子::-通过返回包含一个字符的CharSet进行求值。

使用范围内类原子 :: 范围内类原子非破折号通过评估范围内类原子非破折号来获取CharSet并返回该CharSet来进行评估。

类原子非破折号(21.2.2.18)包括如下额外的评估规则:

使用类原子非破折号 :: 源字符但不是]或者-是通过返回包含由源字符表示的字符的单元素CharSet来评估的。

使用范围内类原子非破折号 :: \ 类转义通过评估类转义来获取CharSet并返回该CharSet来评估。

使用范围内类原子非破折号::源字符但不是]或者-是通过返回包含由源字符表示的字符的单元素CharSet来评估的。

类Escape(21.2.2.19)包括如下额外的评估规则:

使用类转义::二进制转义只用当...评估如下的时候:

  1. 评估二进制转义获得转义Value E。
  2. 断言:E是一个字符。
  3. 让ch是E的字符。
  4. 返回包含字符ch的单元素CharSet。

使用类转义::c类控制字母评估如下所示:

  1. 让ch成为类控制字母匹配的字符。

  2. 让i成为ch的字符值。

  3. 让j是将i除以32的剩余部分。

  4. 返回字符值为j的字符。

B.1.4.1.1运行时语义:CharacterRangeOrUnion联合抽象操作#

抽象操作CharacterRangeOrUnion需要两个CharSet参数A和B,并执行以下步骤:

  1. 如果A不正好包含一个字符,或者B正好不包含一个字符,那么
    1. 让C作为包含单个字符的字符集 - U + 002D(HYPHEN-MINUS)
    2. 返回CharSets A,B和C的联合。
  2. 返回CharacterRange(A, B)。

B.2附加内置属性#

当ECMAScript的宿主是Web浏览器时,以下标准内置对象的附加属性被定义。

B.2.1全局对象的附加属性#

Table 61的入口也被加在Table 7.

Table 61: 附加的使用广泛的内部对象
内部名称 全局名称 ECMAScript
%escape% escape escape 函数 (B.2.1.1)
%unescape% unescape unescape 函数 (B.2.1.2)

B.2.1.1转义(字符串)#

escape函数是全局对象的一个属性。它计算一个新版本的String值,其中某些代码单元已被十六进制转义序列替换。

对于值为0x00FF或更小的被替换的代码单元,使用形式为%xx的两位转义序列。对于代码单位值大于0x00FF的被替换的字符,使用格式为%uxxxx的四位转义序列。

转义函数是%escape%的内在对象。当使用一个字符串参数调用转义函数时,执行以下步骤:

1.将参数转为字符串,ToString(参数)。

2.设长度为字符串中的代码单位数。

3.让R成为空字符串。

4.令k为0。

5.当k<length时,重复以下步骤:

    a.令char是字符串中的索引k处的代码单元(以16位无符号整数表示)。

    b.如果char是“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_+-./”中的代码单元之一,那么

        i.让S是一个包含单个代码单位char的String。

    c.如果char≥256,那么
        i.令S为包含六个代码单元“%uwxyz”的字符串,其中wxyz是编码char值的四个十六进制数字的代码单元。

    d.如果char<256,那么

        i.令S为包含三个代码单元“%xy”的字符串,其中xy是两个编码char值的十六进制数字的代码单元。

    e.让R成为通过连接R和S的先前值计算的新的String值。

    f.将k增加1。

6.返回R。

注意

该编码部分基于RFC 1738中描述的编码,但是在本标准中上述描述的的整个编码是不考虑RFC 1738的内容的。此编码不反映RFC 3986对RFC 1738的更改。

B.2.1.2反转义(字符串)#

unescape函数是全局对象的一个属性。它计算一个新版本的String值,其中可能由转义函数引入的排序的每个转义序列将替换为其所代表的代码单元。

unescape函数是%unescape%内在对象。 当使用一个字符串参数调用unescape函数时,将执行以下步骤:

1.将参数转为字符串,ToString(参数)。

2.设长度为字符串中的代码单位数。

3.让R成为空字符串。

4.令k为0。

5.当k≠length时,重复以下步骤:

    a.令c为字符串中索引k处的代码单位。

    b.如果c是%,那么

        i.如果k≤length-6,字符串内的索引k + 1处的代码单元是u,并且字符串中在索引k + 2,k + 3,k + 4和k + 5处都是十六进制数字,则

            1.令c为代码单位,其值是由字符串中的索引k + 2,k + 3,k + 4和k + 5处的四个十六进制数字表示的整数。

            2.将k增加5。

        ii.如果k≤length-3,并且字符串中在索引k + 1和k + 2处的两个代码单元都是十六进制数字,则

            1.令c为代码单位,其值是由两个零表示加上字符串中在索引k + 1和k + 2处两个十六进制数字。

            2.将k增加2。

    c.令R为通过连接R的先前值和c计算的新的字符串值。

    d.将k增加1。

6.返回R。

B.2.2Object.prototype对象的附加属性#

B.2.2.1Object.prototype.proto#

Object.prototype . proto是一个拥有属性{[[Enumerable]]:false,[[Configurable]]:true}的访问器属性。 [[Get]]和[[Set]]属性定义如下:

B.2.2.1.1get Object.prototype.proto#

[[Get]]属性的值是一个不需要参数的内置函数。 它执行以下步骤:

1.将O转换成对象,ToObject(此值)。

2.返回O,[[GetPrototypeOf]]()。

B.2.2.1.2set Object.prototype.proto#

[[Set]]属性的值是一个内置函数,它接受一个参数proto。 执行时以下步骤:

1.调用RequireObjectCoercible(this value).

2.如果Type(proto)既不是Object也不是Null,则返回undefined。

3.如果Type(O)不是Object,则返回undefined。

4.让状态为O,[[SetPrototypeOf]](proto)。

5.如果status为false,则抛出TypeError异常。

6.返回undefined。

B.2.3String.prototype对象的附加属性#

B.2.3.1String.prototype.substr (start, length)#

substr函数接受不了两个参数,起始位置和长度,返回一个将此对象转换为String的结果的子字符串,从索引开始,长度为传入的长度参数(如果长度未定义,则到String的结尾)。如果start为负,则将其视为sourceLength + start,其中sourceLength是String的长度。结果是一个String值,而不是一个String对象。执行以下步骤:

1.令O为 RequireObjectCoercible(此值)的返回值。

2.令S为ToString(O)的返回值。

3.令intStart为ToInteger(start)的返回值。

4.如果长度未定义,则end为+∞;否则end为ToInteger(length)的返回值。

5.令size是S中代码单元的数量。

6.如果intStart <0,则让intStart为max(size + intStart,0)。

7.令resultLength为min(max(end,0),size - intStart)。

8.如果resultLength≤0,返回空字符串“”。

9.返回一个包含resultLength连续代码单元的字符串,从索引intStart处的代码单元开始。

注意

substr函数是通用的; 它不要求它的这个值是一个String对象。 因此可以将其用作转换其他类型的对象的一种方法。

B.2.3.2String.prototype.anchor ( name )#

当使用参数name调用anchor方法时,将执行以下步骤:

1.让S成为这个值

2.返回CreateHTML(S,“a”,“name”,name)。

B.2.3.2.1Runtime Semantics: CreateHTML ( string, tag, attribute, value )#

抽象操作CreateHTML使用参数string,tag,attribute和value进行调用。 参数tag和attribute必须是String值。 执行以下步骤:

1.令str为RequireObjectCoercible(string)的返回值。

2.令S为ToString(str)的返回值。

3.令p1为连接“<”和tag的字符串。

4.如果attribute不是空串,则

    a.令V为ToString(value)返回值。

    b.假设escapedV是与V相同的String值,只是V中的每个代码单元0x0022(QUOTATION MARK)被单元序列"&quot;"替换。

    c.让p1是以下String值的合并的字符串值:

        p1的字符串值

        代码单元0x0020(SPACE)

        attribute的String值

        代码单位0x003D(EQUALS SIGN)

        代码单位0x0022(QUOTATION MARK)

        escapedV的字符串值

        代码单位0x0022(QUOTATION MARK)

5.令p2为连接p1和“>”的String值。

6.让p3成为p2和S连接的String值。

7.令p4为连接p3,“</”,tag和“>”的String值。

8.返回p4。

B.2.3.3String.prototype.big ()#

当没有参数调用big方法时,采取以下步骤:

1.让S成为这个值。

2.返回CreateHTML(S,“big”,“”,“”)的值。

B.2.3.4String.prototype.blink ()#

当没有参数调用blink方法时,将执行以下步骤:

1.让S成为这个值。

2.返回CreateHTML(S,“blink”,“”,“”)的值。

B.2.3.5String.prototype.bold ()#

当没有参数调用bold方法时,将执行以下步骤:

1.让S成为这个值。

2.返回CreateHTML(S,“b”,“”,“”)的值。

B.2.3.6String.prototype.fixed ()#

当没有参数调用fixed方法时,将执行以下步骤:

1.让S成为这个值。

2.返回CreateHTML(S,“tt”,“”,“”)的值。

B.2.3.7String.prototype.fontcolor ( color )#

当使用参数color调用fontcolor方法时,将执行以下步骤:

1.让S成为这个值。

2.返回CreateHTML(S,“font”,“color”, color)的值。

B.2.3.8String.prototype.fontsize ( size )#

当使用参数size调用fontsize方法时,将执行以下步骤:

1.让S成为这个值。

2.返回CreateHTML(S,“font”,“size”, size)的值。

B.2.3.9String.prototype.italics ()#

当没有参数调用italics方法时,将执行以下步骤:

1.让S成为这个值。

2.返回CreateHTML(S,“i”,“”,“”)的值。

B.2.3.10String.prototype.link ( url )#

当使用参数url调用link方法时,将执行以下步骤:

1.让S成为这个值。

2.返回CreateHTML(S,“a”,“href”, url)的值。

B.2.3.11String.prototype.small ()#

当没有参数调用small方法时,将执行以下步骤:

1.让S成为这个值。

2.返回CreateHTML(S,“small”,“”,“”)的值。

B.2.3.12String.prototype.strike ()#

当没有参数调用strike方法时,将执行以下步骤:

1.让S成为这个值。

2.返回CreateHTML(S,“strike”,“”,“”)的值。

B.2.3.13String.prototype.sub ()#

当没有参数调用sub方法时,将执行以下步骤:

1.让S成为这个值。

2.返回CreateHTML(S,“sub”,“”,“”)的值。

B.2.3.14String.prototype.sup ()#

当没有参数调用sup方法时,将执行以下步骤:

1.让S成为这个值。

2.返回CreateHTML(S,“sup”,“”,“”)的值。

B.2.4Date.prototype对象的附加属性#

B.2.4.1Date.prototype.getYear ( )#

注意

getFullYear方法几乎用于所有目的,因为它避免了“2000年的问题”。

当没有参数调用getYear方法时,执行以下步骤:

1.令t为TimeValue(this value)的返回值。

2.如果t是NaN,则返回NaN。

3.返回YearFromTime(LocalTime(t)) - 1900。

B.2.4.2Date.prototype.setYear (year)#

注意

setYear方法几乎用于所有目的,因为它避免了“2000年的问题”。

当使用一个参数year调用setYear方法时,将执行以下步骤:

1.令t为TimeValue(this value)的返回值。

2.如果t是NaN,令t为+0; 否则,令t为LocalTime(t)。

3.令y为ToNumber(year)的返回值。

4.如果y为NaN,将Date对象的[[DateValue]]内部插槽设置为NaN并返回NaN。

5.如果y不是NaN,0≤Integer(y)≤99,令yyyy为ToInteger(y)+ 1900。

6.否则,令yyyy为y。

7.让d为MakeDay(yyyy,MonthFromTime(t),DateFromTime(t))的返回值。

8.让date为UTC(MakeDate(d,TimeWithinDay(t)))。

9.将此Date对象的[[DateValue]]内部插槽设置为TimeClip(date)。

10.返回此Date对象的[[DateValue]]内部插槽的值。

B.2.4.3Date.prototype.toGMTString ( )#

注意

属性toUTCString是推荐的。toGMTString属性主要用于与旧代码兼容。建议在新的ECMAScript代码中使用toUTCString属性。

作为Date.prototype.toGMTString的初始值的函数对象是与Date.prototype.toUTCString的初始值的函数对象是相同的。

B.2.5RegExp.prototype对象的附加属性#

B.2.5.1RegExp.prototype.compile (pattern, flags )#

当使用参数pattern和flags调用compile方法时,执行以下步骤:

1.让O成为这个值。

2.如果Type(O)不是Object,或者Type(O)是Objec但是O没有[[RegExpMatcher]]内部插槽,那么

    a.抛出TypeError异常。

3.如果Type(pattern)是Object,并且pattern具有[[RegExpMatcher]]内部插槽,那么

    a.如果标志不是未定义,则抛出TypeError异常。

    b.令P为pattern的[[OriginalSource]]内部插槽的值。

    c.令F为pattern的[[OriginalFlags]]内部插槽的值。

4.否则

    a..令P为pattern。

    b.令F为flags。

5.返回RegExpInitialize(O, P, F)。

注意

compile方法使用新的模式和标志重新初始化RegExp对象。使用该方法可以想象成一个断言,其生成的RegExp对象将被多次使用,因此该方法可以作为额外优化的候选方案。

B.3其他附加特性#

B.3.1proto 对象初始化中的属性名称#

以下的早期错误规则被添加到12.2.6.1。当对象常量出现在当对象赋值模式需要时,早期错误规则不适用。此外,在初始解析一个覆盖括号表达式和箭头参数列表时不适用。

对象常量:{属性定义列表}

对象常量:{属性定义列表,}

  • 如果 属性定义列表 的属性名称列表包含任何重复的条目 "proto" 并且这些条目中的至少两个是从表单 属性定义:属性名称:赋值表达式 的制作中获得,就是语法错误。

注意

被 属性名称列表 返回的列表不包括被定义为一个 计算属性名称 的字符串常量属性名称。

在 12.2.6.9 属性定义评估 算法用于 属性定义:属性名称:赋值表达式 的使用被替换为以下定义:

属性定义:

属性名称:

赋值表达式

1.    让propKey成为评估 属性名称 的结果。

2.    ReturnIfAbrupt(propKey)。

3.    让exprValueRef成为评估 赋值表达式 的结果。

4.    让propValue成为GetValue(exprValueRef)的返回值。

5. 如果propKey是线性值 "__proto__" 并且如果IsComputedPropertyKey(propKey)是假,那么

    a.    如果 Type(propValue)是 Object 或 Null ,那么
        i.    返回 object。[[SetPrototypeOf]](propValue)。
    b.    返回 NormalCompletion(empty)。

6.    如果 IsAnonymousFunctionDefinition(AssignmentExpression)是真, 那么

    a.    让hasNameProperty是?HasOwnProperty(propValue,"name")。

    b.    如果hasNameProperty是假,运行SetFunctionName(propValue,propKey)。

7.    断言:enumerable是真。

8.    返回 CreateDataPropertyOrThrow(object,propKey,propValue)。

B.3.2标签函数声明#

在ECMAScript 2015之前,规范 标签声明 不允许将声明标签与一个 函数声明 关联。但是,标签 函数声明 是非严格代码的允许扩展,并且大多数浏览器托管的ECMAScript实现支持该扩展。在ECMAScript 2015中,语法生成 标签声明 允许使用 函数声明 作为一个 标签项,但 13.13.1包括一个如果发生就产生语法错误的早期错误规则。对于Web浏览器的兼容性,该规则会随着添加突出文本而被修改:

标签项:函数声明

  • 如果有任何严格模式源代码与此规则相匹配,则是语法错误。

B.3.3块级函数声明Web遗留兼容性语义#

在ECMAScript 2015之前,ECMAScript规范没有定义一个 函数声明 作为一个元素块语句 语句列表 出现。但是,支持这种形式 函数声明 是允许的扩展,并且大多数浏览器托管的ECMAScript允许它们实现。不幸的是,这些声明的语义在这些实现中是不同的。由于这些语义差异,使用现有的Web ECMAScript代码 块如果使用仅取决于所有这些声明的浏览器实现的语义交集,则级别函数声明仅在浏览器实现之间可移植。以下是该交集语义中的用例:

1. 一个函数被声明,只在一个块内被引用

    •    一个 函数声明, 它的 绑定标识符 名称 f,在封闭函数g的函数代码内,恰好出现一次 ,该声明嵌套在一个 块中。

    •    在g的函数代码中没有发生不是声明的f的其他声明 var。

    •    所有作为 标识符参考 出现的 f是在包含f的声明块的 声明列表 内。

2. 一个函数被声明并可能在一个单一块中使用,但也可被不包含在单一块中的内部函数定义引用。 

    •    一个 函数声明, 它的 绑定标识符 名称 f,在封闭函数g的函数代码内,恰好出现一次 ,该声明嵌套在一个 块中。

    •    在g的函数代码中没有发生不是声明的f的其他声明 var。

    •    可能出现作为 标识符引用 的f ,在含f的声明的块的 声明列表 中 。

    •    f 至少有一次作为 标识符引用 出现在另一个函数h中, 该函数嵌套在g中,并且没有其它声明f遮盖了对f的引用从h中。

    •    所有的 h的调用发生在f的声明被评估之后。

3. 一个函数被声明并且可能在单个块内使用,但是在随后的块中也被引用。

    •    一个 函数声明, 它的 绑定标识符 名称 f,在封闭函数g的函数代码内,恰好出现一次 ,该声明嵌套在一个 块中。

    •    在g的函数代码中没有发生不是声明的f的其他声明 var。

    •    可能出现作为 标识符引用 的f ,在含f的声明的块的 声明列表 中 。

    •    f 至少有一次作为 标识符引用 出现在另一个函数密码g中, 该函数在词汇方面。

第一个用例是与ECMAScript 2015提供的块层函数声明的语义是相互兼容的。使用该用例的任何预先存在的ECMAScript代码将使用本规范第9,13和14条定义的块级别函数声明语义进行操作。

第二和第三个用例的ECMAScript 2015互操作性需要对以下语义进行扩展:条款9,条款 14,条款 18.2.1 和条款 15.1.11 。字符串值

如果一个ECMAScript运用具有报告诊断警告消息的机制,一个警告应当产生当密码包含一个 函数声明 ,为了它这些兼容语义被应用和介绍与不兼容的语义的明显不同。例如,如果因为引入将创建一个早期错误而没有引入var绑定,不应该产生警告信息。

B.3.3.1函数声明实例化的更改#

在 函数声明实例化 中执行以下步骤来代替步骤29:

1    如果严格的是假, 那么

    a)    对于每一个 函数声明f直接包含在块,case子句,或default字句的 声明列表 中,

        i.    让F成为 函数声明f 的绑定标识符 的 字符串值。

        ii.    如果更换 函数声明f 与一个 变量声明,这个声明有F作为 绑定标识符 不会为 func产生任何早误差,而且F不是 证据列表 的 绑定名字 的 一个元素,那么

            1.    注意对于F的var绑定只在这里实例化,如果它既不是 var声明名称,一个正式变量的名称,也不是另一个 函数声明。 

            2.    如果实体化Var名称 不包含F,那么

                a)    执行!varEnvRec . 创建易变绑定(F,false)。

                b)    执行varEnvRec . 实现绑定(F,undefined)。

                c)    将F附加到 实例化VAR名称。

            3.    当 函数声明f 评估时,执行以下步骤代替 函数声明 评估算法提供于14.1.21:

                a)    让fenv成为运行执行上下文的 变量环境。

                b)    让fenvRec成为fenv的 环境记录。

                c)    让benv成为运行执行上下文的词汇环境。

                d)    让benvRec是benv的 环境记录。

                e)    让fobj为benvRec .GetBindingValue(F,false)。

                f)    执行!fenvRec .SetMutableBinding(F,fobj,false)。

                g)    返回 NormalCompletion(empty)。

B.3.3.2对全局声明实例化的更改#

在 全体声明实例化 中执行以下步骤来代替步骤14:

1    让 严格 成为 脚本 的IsStrict

2    如果 严格 是false, 那么

    a)    让声明函数或Var名称成为一个新的空列表。

    b)    追加到声明函数或Var名称,声明函数名称 的元素。

    c)    追加到声明函数或Var名称,声明Var名称 的元素。

    d)    对于每一个 函数声明 f, 直接包含在语句列表 的一个 块,情况字句,或default子句的包含 脚本 的 声明列表 中,

            i.    让F为 函数声明 f 的 绑定标识符 的 字符串值。

            ii.    如果更换 函数声明f 与一个 变量声明,这个声明有F作为 绑定标识符 不会为 脚本 产生任何早误差,那么

                1    如果envRec .HasLexicalDeclaration(F)是false, 那么

                    a)    让fnDefinable为envRec.CanDeclareGlobalFunction(F)的返回值。

                    b)    如果fnDefinable是真, 那么

                        i.    注意对于F的var绑定只在这里实例化,如果它既不是 var声明名称,也不是另一个 函数声明。

                        ii.    如果声明函数或Var名称 不包含F,那么

                            i.    执行envRec.CreateGlobalFunctionBinding(F, undefined, false).。

                            ii.    将F附加到 声明函数或Var名称。

                            iii.    当 函数声明f 评估时,执行以下步骤代替 函数声明 评估算法提供于14.1.21:

                                i.    让 genv 成为运行执行上下文的 变量环境。

                                ii.    让genvRec是genv的环境记录。

                                iii. 让benv成为运行执行上下文的词汇环境。

                                iv.    让benvRec是benv的环境记录。

                                v.    让fobj为benvRec.GetBindingValue(F, false)的返回值。

                                vi.    执行genvRec .SetMutableBinding(F,fobj,flase)。

                                vii.返回 NormalCompletion(empty)。

B.3.3.3Eval声明实例化的修改#

在Eval声明实例化期间执行以下步骤来代替步骤9:

1. 如果严格的是false, 然后

    a)    让declaredFunctionOrVarNames成为一个新的空白列表。

    b)    追加到declaredFunctionOrVarNames的元素declaredFunctionNames。

    c)    追加到declaredFunctionOrVarNames的元素declaredVarNames。

    d)    对于每一个函数声明f直接包含在语句列表 的一个 块, Case子句, 或者包含在body内Default子句,

        i.    让F为字符串值的绑定标志符 的 函数声明 f。

        ii.    如果更换 函数声明 f与一个变量语句有F作为绑定标志符不会产生任何前期错误,然后

            1.    让bindExists是假。

            2.    让thisLex是lexEnv。

            3.    断言:以下循环将终止。

            4.    重复whileLex与varEnv不同,

                a)    让thisEnvRec是thisLex的EnvironmentRecord。

                b)    如果这个EnvRec不是一个对象环境记录, 然后

                    i.    如果这个EnvRec .HasBinding(F)是true, 然后

                        i.    让bindExists是true。

                c)    让这个Lex是这个外部环境参考。

            5.    如果bindingExists是假而varEnvRec是全局的环境记录, 然后

                a)    如果varEnvRec .HasLexicalDeclaration(F)是假, 然后

                    i.    让fnDefinable为varEnvRec .CanDeclareGlobalFunction(F)的返回值。

                b)    否则,

                    i.    让fnDefinable 为假。

            6. 否则,

                a)    让fnDefinable 为true。

            7. 如果bindingExists是假和fnDefinable是true, 然后

                a)    如果declaredFunctionOrVarNames不包含F,那么

                    i.    如果varEnvRec是全局的环境记录, 然后

                        i.    执行varEnvRec .CreateGlobalFunctionBinding(F,undefined, true)。

                        ii. 否则

                            i.让bindExists为varEnvRec .HasBinding(F)的返回值

                            ii.如果bindingExists是假,那么

                                i.执行varEnvRec .CreateMutableBinding(F,true)。

                                ii.执行varEnvRec .InitializeBinding(F,undefined)。

                        iii.将F加到declaredFunctionOrVarNames。

                b) 当函数声明f被执行时,执行以下步骤代替14.1.21中函数声明执行算法:

                    i.让genv成为运行执行上下文的变量环境。

                    ii.让genvRec成为genv的环境记录。

                    iii.让benv成为运行执行上下文的词汇环境。

                    iv.让benvRec是benv的环境记录。

                    v.让fobj成为benvRec .GetBindingValue(F,false)的返回值。

                    vi.执行genvRec.SetMutableBinding(F,fobj,false)。

                    vii.返回NormalCompletion(empty)。

B.3.4If语句中的函数声明规则#

If语句的规则在13.6中增加了这些:

if语句[Yield, Return]:

if(表达式[In, ?Yield])函数声明[?Yield]else语句[?Yield, ?Return]

if(表达式[In, ?Yield])语句[?Yield, ?Return]else函数声明[?Yield]

if(表达式[In, ?Yield])函数声明[?Yield]else函数声明[?Yield]

if(表达式[In, ?Yield])函数声明[?Yield]

上述规则仅适用于解析不严格模式代码的代码。如果任何这样的代码与这些规则之一相匹配,则该代码的后续处理将发生,就好像每个匹配发生的函数声明[?Yield]都是源代码中占据该位置的的唯一语句列表项。

B.3.5Catch块中的变量语句#

13.15.1中的内容改为如下:

Catch:catch(参数)

  • 如果Catch参数中的绑定名称包含任何重复的元素,那么它是一个语法错误。

  • 如果Catch参数的绑定名称中的任何元素同时出现在块的词汇声明中,则是语法错误。

  • 如果Catch参数的绑定名称中的任何元素同时出现在块的Var声明中,则它是语法错误,除非Catch参数为Catch参数:绑定标志符,并且该元素仅受变量语句,for语句的变量声明列表或For-in语句的For绑定的约束。

注意

Catch子句的块可能包含绑定名称的变量声明,该名称也受Catch参数约束。在运行时,这种绑定在变量声明环境中被实例化。它们不会影响由Catch参数引入的相同命名的绑定,因此对于这种var声明的初始化将分配给相应的catch参数,而不是var绑定。正常静态语义规则的宽松不适用于仅由for-of语句约束的名称。

此修改的行为也适用于包含在Catch子句块中的eval直接调用引入的var和函数声明。这种改变是通过修改18.2.1.2中的算法来实现的,如下所示:

步骤5.d.ii.2.a.i替换为:

  1. 如果thisEnvRec不是Catch子句的环境记录,则抛出一个SyntaxError异常。

  2. 如果名称是以函数声明,变量语句,for语句的变量声明列表或for-in语句的For绑定以外的任何句法形式绑定的,则会引发SyntaxError异常。

步骤9.d.ii.4.b.i.i替换为:

  1. 如果此EnvRec不是Catch子句的环境记录,则允许bindingExists为true。

译者tsy_77尚未开通打赏功能

相关文章