页面模式偏好

11 ECMAScript 语言:源文本

11.1 源文本

语法

SourceCharacter :: any Unicode code point

ECMAScript 源文本是 Unicode 码点序列。在 ECMAScript 文法允许的位置,U+0000 到 U+10FFFF 的所有 Unicode 码点值(包括代理码点)都可以出现在 ECMAScript 源文本中。用于存储和交换 ECMAScript 源文本的实际编码与本规范无关。无论外部源文本采用何种编码,符合规范的 ECMAScript 实现都会像处理等效的 SourceCharacter 值序列一样处理源文本,其中每个 SourceCharacter 都是一个 Unicode 码点。符合规范的 ECMAScript 实现不要求对源文本执行任何规范化,也不要求表现得如同对源文本执行了规范化。

组合字符序列的各组成部分会被视为独立的 Unicode 码点,即使用户可能会将整个序列视为单个字符。

注

在字符串字面量、正则表达式字面量、模板字面量和标识符中,任何 Unicode 码点也都可以使用显式表示码点数值的 Unicode 转义序列来表示。在注释中,这种转义序列实际上会作为注释的一部分而被忽略。

ECMAScript 与 Java 编程语言在 Unicode 转义序列的行为方面有所不同。例如,在 Java 程序中,如果 Unicode 转义序列 \u000A 出现在单行注释中,它会被解释为行终止符(Unicode 码点 U+000A 是 LINE FEED (LF)),因此下一个码点不属于该注释。类似地,如果 Unicode 转义序列 \u000A 出现在 Java 程序的字符串字面量中,它同样会被解释为行终止符,而字符串字面量中不允许出现行终止符——必须写成 \n 而不是 \u000A,才能让 LINE FEED (LF) 成为字符串字面量值的一部分。在 ECMAScript 程序中,出现在注释内的 Unicode 转义序列永远不会被解释,因此不会参与终止注释。类似地,出现在 ECMAScript 程序字符串字面量中的 Unicode 转义序列始终构成该字面量的一部分,绝不会被解释为行终止符,也不会被解释为可能终止该字符串字面量的码点。

11.1.1 Static Semantics: UTF16EncodeCodePoint ( codePoint )

抽象操作 UTF16EncodeCodePoint,接收参数 codePoint (Unicode 码点);返回值:String。 调用时执行以下步骤:

  1. 断言:0 ≤ codePoint ≤ 0x10FFFF。
  2. 如果 codePoint ≤ 0xFFFF,则返回由数值为 codePoint 的码元组成的 String 值。
  3. 令 cu1 为数值为 floor((codePoint - 0x10000) / 0x400) + 0xD800 的码元。
  4. 令 cu2 为数值为 ((codePoint - 0x10000) modulo 0x400) + 0xDC00 的码元。
  5. 返回 cu1 和 cu2 的字符串连接。

11.1.2 Static Semantics: CodePointsToString ( text )

抽象操作 CodePointsToString,接收参数 text (a sequence of Unicode code points);返回值:String。 它按照 6.1.4 中的描述,将 text 转换为 String 值。 调用时执行以下步骤:

  1. 令 result 为空 String。
  2. 对 text 的每个码点 codePoint,执行
    1. 将 result 设置为 result 和 UTF16EncodeCodePoint(codePoint) 的字符串连接。
  3. 返回 result。

11.1.3 Static Semantics: UTF16SurrogatePairToCodePoint ( lead, trail )

抽象操作 UTF16SurrogatePairToCodePoint,接收参数 lead (码元) 和 trail (码元);返回值:码点。 将构成 UTF-16 代理对的两个码元转换为一个码点。 调用时执行以下步骤:

  1. 断言:lead 是前导代理,trail 是尾随代理。
  2. 令 codePoint 为 (lead - 0xD800) × 0x400 + (trail - 0xDC00) + 0x10000。
  3. 返回码点 codePoint。

11.1.4 Static Semantics: CodePointAt ( string, position )

抽象操作 CodePointAt,接收参数 string (String) 和 position (非负整数);返回值:记录 (字段:[[CodePoint]] (码点), [[CodeUnitCount]] (正整数), [[IsUnpairedSurrogate]] (Boolean))。 它按照 6.1.4 中的描述,将 string 解释为 UTF-16 编码码点序列,并从索引 position 处的码元开始读取其中的单个码点。 调用时执行以下步骤:

  1. 令 size 为 string 的长度。
  2. 断言:position ≥ 0 且 position < size。
  3. 令 first 为 string 中索引 position 处的码元。
  4. 令 codePoint 为数值与 first 的数值相同的码点。
  5. 如果 first 既不是前导代理也不是尾随代理,则
    1. 返回 Record { [[CodePoint]]: codePoint, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: false }。
  6. 如果 first 是尾随代理或 position + 1 = size,则
    1. 返回 Record { [[CodePoint]]: codePoint, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }。
  7. 令 second 为 string 中索引 position + 1 处的码元。
  8. 如果 second 不是尾随代理,则
    1. 返回 Record { [[CodePoint]]: codePoint, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }。
  9. 将 codePoint 设置为 UTF16SurrogatePairToCodePoint(first, second)。
  10. 返回 Record { [[CodePoint]]: codePoint, [[CodeUnitCount]]: 2, [[IsUnpairedSurrogate]]: false }。

11.1.5 Static Semantics: StringToCodePoints ( string )

抽象操作 StringToCodePoints,接收参数 string (String);返回值:列表 (元素:码点)。 它返回按照 6.1.4 中的描述,将 string 解释为 UTF-16 编码 Unicode 文本后得到的 Unicode 码点序列。 调用时执行以下步骤:

  1. 令 codePoints 为新的空 List。
  2. 令 size 为 string 的长度。
  3. 令 position 为 0。
  4. 当 position < size 时,重复执行,
    1. 令 codePoint 为 CodePointAt(string, position)。
    2. 将 codePoint.[[CodePoint]] 追加到 codePoints。
    3. 将 position 设置为 position + codePoint.[[CodeUnitCount]]。
  5. 返回 codePoints。

11.1.6 Static Semantics: ParseText ( sourceText, goalSymbol )

抽象操作 ParseText,接收参数 sourceText ((String 或 a sequence of Unicode code points)) 和 goalSymbol (a nonterminal in one of the ECMAScript grammars);返回值:(解析节点 或 a non-empty List of SyntaxError objects)。 调用时执行以下步骤:

  1. 如果 sourceText 是 String,则将 sourceText 设置为 StringToCodePoints(sourceText)。
  2. 尝试使用 goalSymbol 作为目标符号解析 sourceText,并分析解析结果是否存在任何提前错误条件。实现可以按实现定义的方式交错执行解析和提前错误检测。
  3. 如果解析成功且未发现提前错误,则返回解析所得解析树根部的 Parse Node(goalSymbol 的实例)。
  4. 返回由一个或多个表示解析错误和/或提前错误的 SyntaxError 对象组成的 List。如果存在多个解析错误或提前错误,则列表中错误对象的数量和顺序由实现定义,但至少必须存在一个。
注 1

考虑这样一段文本:它在某个位置存在提前错误,并且在之后的位置还存在语法错误。先执行一次解析再执行提前错误检查的实现,可能会报告语法错误而不继续执行提前错误检查。将这两项活动交错执行的实现,可能会报告提前错误而不继续寻找语法错误。第三种实现可能会同时报告两个错误。所有这些行为都符合规范。

注 2

另请参见条款 17。

11.2 源代码的类型

ECMAScript 代码有四种类型:

注 1

函数代码通常作为函数定义(15.2)、箭头函数定义(15.3)、方法定义(15.4)、生成器函数定义(15.5)、异步函数定义(15.8)、异步生成器函数定义(15.6)和异步箭头函数(15.9)的主体提供。函数代码也可以从 Function 构造函数(20.2.1.1)、GeneratorFunction 构造函数(27.6.1.1)、AsyncFunction 构造函数(27.10.1.1)和 AsyncGeneratorFunction 构造函数(27.7.1.1)的参数派生。

注 2

将 BindingIdentifier 包含在函数代码中的实际效果是:严格模式代码的提前错误会应用于这样的 BindingIdentifier——它是函数的名称,而该函数的主体包含 Use Strict 指令,即使周围代码不是严格模式代码。

11.2.1 指令序言和 Use Strict 指令

指令序言是一个 FunctionBody、ScriptBody 或 ModuleBody 开头作为初始 StatementListItem 或 ModuleItem 出现的最长 ExpressionStatement 序列,其中序列中的每个 ExpressionStatement 都完全由一个 StringLiteral 标记后跟一个分号组成。分号可以显式出现,也可以通过自动分号插入(12.10)插入。指令序言可以是空序列。

Use Strict 指令是指令序言中的一个 ExpressionStatement,其 StringLiteral 恰好是码点序列 "use strict" 或 'use strict'。Use Strict 指令不得包含 EscapeSequence 或 LineContinuation。

指令序言可以包含多个 Use Strict 指令。不过,实现可以在出现这种情况时发出警告。

注

在对包含它们的产生式求值期间,指令序言中的 ExpressionStatement 会正常求值。实现可以为出现在指令序言中且不是 Use Strict 指令的 ExpressionStatement 定义实现特定的含义。如果存在适当的通知机制,并且实现在指令序言中遇到既不是 Use Strict 指令、也没有实现所定义含义的 ExpressionStatement,则实现应当发出警告。

11.2.2 严格模式代码

ECMAScript 句法单元可以使用无限制模式或严格模式的语法和语义进行处理(4.3.2)。在以下情况下,代码被解释为严格模式代码:

不是严格模式代码的 ECMAScript 代码称为非严格代码。

11.2.2.1 Static Semantics: IsStrict ( parseNode )

抽象操作 IsStrict,接收参数 parseNode (解析节点);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 parseNode 匹配的源文本是严格模式代码,则返回 true。
  2. 返回 false。

11.2.3 非 ECMAScript 函数

ECMAScript 实现可以支持对函数异质对象进行求值,而这些对象的求值行为以 ECMAScript 源文本之外某种宿主定义的可执行代码形式表示。从调用此类函数对象或被此类函数对象调用的 ECMAScript 代码角度来看,无法观察到函数对象究竟是在 ECMAScript 代码中定义的,还是内置函数。