Skip to content

Latest commit

 

History

History
1076 lines (777 loc) · 67.2 KB

Expressions.md

File metadata and controls

1076 lines (777 loc) · 67.2 KB

主值表达式

   PrimaryExpression :        this         Identifier        Literal        **        **        (  )**

this关键字

this 关键字执行为当前执行环境的 this 绑定

标识符引用

Identifier 的执行遵循 10.3.1 所规定的标识符查找。标识符执行的结果总是一个 Reference 类型的值。

字面量引用

Literal 按照 7.8 所描述的方式执行。

数组初始化

数组初始化是一个以字面量的形式书写的描述数组对象的初始化的表达式。它是一个零个或者多个表达式的序列,其中每一个表示一个数组元素,并且用方括号括起来。元素并不一定要是字面量,每次数组初始化执行时它们都会被执行一次。

数组元素可能在元素列表的开始、结束,或者中间位置以逗号取代。当元素列表中的一个逗号的前面没有 **(如,一个逗号在另一个逗号之前。)的情况下,缺失的数组元素仍然会对数组长度有贡献,并且增加后续元素的索引值。以逗号省略的数组元素是 undefined。假如元素在数组末尾被省略,那么元素不会贡献数组长度。

   ArrayLiteral :        [  ]**        [  ]**        [  ,  ]

   ElementList :                  ,  **

   Elision :        ,         ,**

产生式 ** : [ **opt ] 按照下面的过程执行 :

  1. array 为以表达式 new Array() 完全一致的方式创建一个新对象的结果,其中 Array 是一个标准的内置构造器。
  2. pad 为解释执行 ** 的结果;如果不存在的话,使用数值 0
  3. 以参数 "length"padfalse 调用 array[[Put]] 内置方法
  4. 返回 array

产生式 ** : [ ** ] 按照下面的过程执行 :

  1. 返回解释执行 ** 的结果。

产生式 ** : [ ** , **opt ] 按照下面的过程执行:

  1. array 为解释执行 ** 的结果。
  2. pad 为解释执行 ** 的结果;如果不存在的话,使用数值 0
  3. len 为以参数 "length" 调用 array[[Get]] 内置方法的结果。
  4. 以参数 "length"ToUint32(pad+len) 和 false 调用 array[[Put]] 内置方法。
  5. 返回 array

产生式 ** : **opt ** 按照下面的过程执行 :

  1. array 为以表达式 new Array() 完全一致的方式创建一个新对象的结果,其中 Array 是一个标准的内置构造器。
  2. firstIndex 为解释执行 ** 的结果;如果不存在的话,使用数值 0
  3. initResult 为解释执行 ** 的结果。
  4. initValueGetValue(initResult)。
  5. 以参数 ToString(firstIndex)、属性描述对象 { [[Value]]: initValue, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true} 和 false 调用 array[[DefineOwnProperty]] 内置方法。
  6. 返回 array

产生式 ** : ** , **opt ** 按照下面的过程执行 :

  1. array 为解释执行 ** 的结果。
  2. pad 为解释执行 ** 的结果;如果不存在的话,使用数值 0
  3. initResult 为解释执行 ** 的结果。
  4. initValueGetValue(initResult)。
  5. len 为以参数 "length" 调用 array[[Get]] 内置方法的结果。
  6. 以参数 ToString(ToUint32(pad+len)) 和属性描述对象 { [[Value]]: initValue, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true} 和 false 调用 array[[DefineOwnProperty]] 内置方法。
  7. 返回 array

产生式 ** : , 按照下面的过程执行 :

  1. 返回数值 1

产生式 ** : ** , 按照下面的过程执行 :

  1. preceding 为解释执行 ** 的结果。
  2. 返回 preceding+1

对象初始化

对象初始化是一个以直接量的方式描述对象的初始化过程的表达式。它是用花括号括起来的由零或者多对属性名 / 关联值组成的列表,值不需要是直接量,每次对象初始化被执行到时他们会执行一次。

   ObjectLiteral :        { }         {  }**        {  , }**

   PropertyNameAndValueList :        **         , 

   PropertyAssignment :         :         get  ( ) { FunctionBody }**        set  (  ) { FunctionBody }

   PropertyName :        IdentifierName        StringLiteral        NumericLiteral

   PropertySetParameterList :        Identifier

产生式 ** : { } 按照下面的过程执行 :

  1. 如同以表达式 new Object() 创建新对象,其中 Object 是标准的内置构造器。

产生式 s ** : { ** } 以及 ** : { ** ,} 按照下面的过程执行 :

  1. 返回解释执行 ** 的结果。

产生式 ** : ** 按照下面的过程执行 :

  1. obj 为以表达式 new Object() 完全一致的方式创建一个新对象的结果,其中 Object 是一个标准的内置构造器。
  2. propId 为解释执行 ** 的结果。
  3. 以参数 propId.namepropId.descriptorfalse 调用 obj[[DefineOwnProperty]] 内置方法。
  4. 返回 obj

产生式 ** : ** , ** 按照下面的过程执行 :

  1. obj 为解释执行 ** 的结果。
  2. propId 为解释执行 ** 的结果。
  3. previous 为以参数 propId.name 调用 obj[[GetOwnProperty]] 内置方法的结果。
  4. 如果 previous 不是 undefined,且当以下任意一个条件为 true 时,则抛出一个 SyntaxError 异常:

如果以上步骤抛出一个 SyntaxError,那么实现应该把这个错误视为早期错误

产生式 ** : ** : ** 按照下面的过程执行 :

  1. propName 为解释执行 ** 的结果。
  2. exprValue 为解释执行 ** 的结果。
  3. propValueGetValue(exprValue)。
  4. desc属性描述对象 {[[Value]]: propValue, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}。
  5. 返回 属性标识符 (propName, desc)。

产生式 ** : get ** ( ) { FunctionBody } 按照下面的过程执行:

  1. propName 为解释执行 ** 的结果。
  2. closure 为根据 13.2 的定义,以空参数列表和 FunctionBody 函数体创建的一个新的函数对象。传入当前执行中的执行环境的 LexicalEnvironment 作为 Scope。假如 ** 包含在严格模式代码中或者 FunctionBody严格模式代码,传入 true 为严格模式标志。
  3. desc属性描述对象 {[[Get]]: closure, [[Enumerable]]: true, [[Configurable]]: true}。
  4. 返回 属性标识符 (propName, desc)。

产生式 ** : set ** '''( ''' '''' ) { FunctionBody } 按照下面的过程执行:

  1. propName 为解释执行 ** 的结果。
  2. closure 为按照 13.2 规定,以 ** 作为参数列表和 FunctionBody 函数体创建的一个新的函数对象。传入当前执行中的执行环境的 LexicalEnvironment 作为 Scope。假如 ** 包含在严格模式代码中或者 FunctionBody严格模式代码,传入 true 为严格模式标志。
  3. desc属性描述对象 {[[Set]]: closure, [[Enumerable]]: true, [[Configurable]]: true}。
  4. 返回属性标识符 (propName, desc)。

假如 FunctionBody严格模式或者被包含在严格模式代码内,** 中的 "eval"** 或者 "arguments" 作为标识符将会是一个语法错误。

产生式 ** ''': ''' IdentifierName 按照下面的过程执行:

  1. 返回一个包含跟 IdentifierName 完全相同的字符序列的字符串值。

产生式 ** ''': ''' StringLiteral 按照下面的过程执行:

  1. 返回 StringLiteral 的字符串值。

产生式 ** : NumericLiteral 按照下面的过程执行:

  1. nbr 为求 NumericLiteral 值的结果。
  2. 返回 ToString(nbr)。

群组运算符

产生式 ** : ( ** ) 按照下面的过程执行:

  1. 返回执行 ** 的结果。这可能是一个 Reference

左值表达式

   MemberExpression :        **        FunctionExpression         [  ]         . IdentifierName        new  **

   NewExpression :        **        new **

   CallExpression :                           [  ]         .** IdentifierName

   Arguments :        ( )        (  )**

   ArgumentList :        **         , 

   LeftHandSideExpression :        **        **

属性访问

属性是通过 name 来访问的,可以使用点表示法访问

    . IdentifierName     . IdentifierName

或者括号表示法访问

    [  ]      [  ]

点表示法是根据以下的语法转换解释

    .** IdentifierName

这会等同于下面这个行为

    [  ]**

类似地,

    .** IdentifierName

是等同于下面的行为

    [  ]**

是一个字符串字面量,它与 Unicode 编码后的 IdentifierName 包含相同的字符序列。

产生式 ** : ** [ ** ] 按照下面的过程执行:

  1. baseReference 为解释执行 ** 的结果。
  2. baseValueGetValue(baseReference)。
  3. propertyNameReference 为解释执行 ** 的结果。
  4. propertyNameValueGetValue(propertyNameReference)。
  5. 调用 CheckObjectCoercible(baseValue)。
  6. propertyNameStringToString(propertyNameValue)。
  7. 如果正在执行中的语法产生式包含在严格模式代码当中,令 stricttrue,否则令 strictfalse
  8. 返回一个值类型的引用,其基值为 baseValue 且其引用名为 propertyNameString,严格模式标记为 strict

产生** : ** [ ** **]的执行方式与以上执行过程完全一样,除非在步骤1已经执行过。

new 运算符

产生式 ** : new ** 按照下面的过程执行:

  1. ref 为解释执行 ** 的结果。
  2. constructorGetValue(ref)。
  3. 如果 Type(constructor) 不是 Object,抛出一个 TypeError 异常。
  4. 如果 constructor 没有实现 [[Construct]] 内置方法,抛出一个 TypeError 异常。
  5. 返回调用 constructor[[Construct]] 内置方法的结果,传入按无参数传入参数列表(就是一个空的参数列表)。

产生式 ** : new ** ** 按照下面的过程执行 :

  1. ref 为解释执行 ** 的结果。
  2. constructorGetValue(ref)。
  3. argList 为解释执行 ** 的结果,是一个参数值的内部列表(11.2.4)。
  4. 如果 Type(constructor) 不是 Object,抛出一个 TypeError 异常。
  5. 如果 constructor 没有实现 [[Construct]] 内置方法,抛出一个 TypeError 异常。
  6. 返回以 argList 为参数调用 constructor[[Construct]] 内置方法的结果。

函数调用

产生式 ** : ** ** 按照下面的过程执行 :

  1. ref 为解释执行 ** 的结果。

  2. funcGetValue(ref)。

  3. argList 为解释执行 ** 的结果,产生参数值们的内部列表(参见 11.2.4)。

  4. 如果 Type(func) 不是 Object,抛出一个 TypeError 异常。

  5. 如果 IsCallable(func) 为 false,抛出一个 TypeError 异常。

  6. 如果 Type(ref) 为 Reference,那么

    1. 如果 IsPropertyReference(ref) 为 true,那么

      1. thisValueGetBase(ref)。
    2. 否则,ref 的基值是一个环境记录项

      1. thisValue 为调用 GetBase(ref) 的 ImplicitThisValue 具体方法的结果。
  7. 否则,Type(ref) 不是 Reference

    1. thisValueundefined
  8. 返回调用 func[[Call]] 内置方法的结果,传入 thisValue 作为 this 值和列表 argList 作为参数列表。

参数列表

产生式 ** : ( ) 按照下面的过程执行:

  1. 返回一个空列表

产生式 ** : '''( ''' ** ) 按照下面的过程执行:

  1. 返回解释执行 ** 的结果。

产生式 ** : ** 按照下面的过程执行:

  1. ref 为解释执行 ** 的结果。
  2. argGetValue(ref)。
  3. 返回唯一的项目是 arg列表

产生式 ** : ** , ** 按照下面的过程执行 :

  1. precedingArgs 为解释执行 ** 的结果。
  2. ref 为解释执行 ** 的结果。
  3. argGetValue(ref)。
  4. 返回一个列表,长度比 precedingArgs 大 1 且它的项目为 precedingArgs 的项目按顺序在后面接 argarg 就是这个新的列表的最后一个项目。

函数表达式

产生式 ** : FunctionExpression 按照下面的过程执行 :

  1. 返回解释执行 FunctionExpression 的结果。

后缀表达式

   PostfixExpression :        **         [no LineTerminator here++          [no LineTerminator here--

后缀自增运算符

产生式 PostfixExpression : ** [no LineTerminator here] ++ 按照下面的过程执行:

  1. lhs 为解释执行 ** 的结果。

  2. 假如以下所有条件都为真,抛出一个 SyntaxError 异常:

  3. oldValueToNumer(GetValue(lhs))。

  4. newValue1 加上 oldValue 的结果,使用与 + 运算符 相同的规则(参见 11.6.3)。

  5. 调用 PutValue(lhs, newValue)。

  6. 返回 oldValue

后缀自减运算符

产生式 PostfixExpression : ** [no LineTerminator here] '''-- ''' 按照下面的过程执行:

  1. lhs 为解释执行 ** 的结果。

  2. 假如以下所有条件都为真,抛出一个 SyntaxError 异常:

  3. oldValueToNumer(GetValue(lhs))。

  4. newValue 为从 oldValue 减掉 1 的结果,使用与 - 运算符 相同的规则(参见 11.6.3)。

  5. 调用 PutValue(lhs, newValue)。

  6. 返回 oldValue

一元运算符

   UnaryExpression :        **        delete **        void **        typeof **        ++ **        -- **        + **        - **        ~ **        ! **

delete 运算符

产生式 ** : delete ** 按照下面的过程执行 :

  1. ref 为解释执行 ** 的结果。

  2. 如果 Type(ref) 不是 Reference,返回 true

  3. IsUnresolvableReference(ref) 则

    1. 如果 IsStrictReference(ref) 为 true,抛出一个 SyntaxError 异常。
    2. 否则,返回 true
  4. 如果 IsPropertyReference(ref) 为 true 则:

    1. 返回以 GetReferencedName(ref) 和 IsStrictReference(ref) 做为参数调用 ToObject(GetBase(ref)) 的 [[Delete]] 内置方法的结果。
  5. 否则,ref 是到环境记录项绑定的 Reference,所以:

    1. 如果 IsStrictReference(ref) 为 true,抛出一个 SyntaxError 异常。
    2. bindingsGetBase(ref)。
    3. 返回以 GetReferencedName(ref) 为参数调用 bindingsDeleteBinding 具体方法的结果。

void 运算符

产生式 ** : void ** 按照下面的过程执行 :

  1. expr 为解释执行 ** 的结果。
  2. 调用 GetValue(expr)。
  3. 返回 undefined

typeof 运算符

产生式 ** : typeof ** 按照下面的过程执行 :

  1. val 为解释执行 ** 的结果。

  2. 如果 Type(val) 为 Reference,则:

    1. 如果 IsUnresolvableReference(val) 为 true,返回 "undefined"
    2. valGetValue(val)。
  3. 返回根据 表20Type(val) 决定的字符串。

|---|---| |val 类型|结果| |Undefined|"undefined"| |Null|"object"| |Boolean|"boolean"| |Number|"number"| |String|"string"| |Object(原生,且没有实现 [[Call]])|"object"| |Object(原生或者宿主且实现了 [[Call]])|"function"| |Object(宿主且没实现 [[Call]])|由实现定义,但不能是 "undefined""boolean""number""string"。|

前自增运算符

产生式 ** : ++ ** 按照下面的过程执行:

  1. expr 为解释执行 ** 的结果。

  2. 假如以下所有条件都为真,抛出一个 SyntaxError 异常:

  3. oldValueToNumer(GetValue(expr))。

  4. newValue1 加上 oldValue 的结果,使用与 + 运算符 相同的规则(参见 11.6.3)。

  5. 调用 PutValue(expr, newValue)。

  6. 返回 newValue

前自减运算符

产生式 ** : '''-- ''' ** 按照下面的过程执行:

  1. expr 为解释执行 ** 的结果。

  2. 假如以下所有条件都为真,抛出一个 SyntaxError 异常:

  3. oldValueToNumer(GetValue(expr))。

  4. newValue 为从 oldValue 减掉 1 的结果,使用与 - 运算符 相同的规则(参见 11.6.3)。

  5. 调用 PutValue(expr, newValue)。

  6. 返回 newValue

一元 + 运算符

产生式 ** : + ** 按照下面的过程执行 :

  1. expr 为解释执行 ** 的结果。
  2. 返回 ToNumber(GetValue(expr))。

一元 - 运算符

产生式 ** : - ** 按照下面的过程执行:

  1. expr 为解释执行 ** 的结果。
  2. oldValueToNumber(GetValue(expr))。
  3. 如果 oldValueNaN,返回 NaN
  4. 返回 oldValue 取负(即,算出一个数字相同但是符号相反的值)的结果。

按位非运算符

产生式 ** : ~ ** 按照下面的过程执行:

  1. expr 为解释执行 ** 的结果。
  2. oldValueToInt32(GetValue(expr))。
  3. 返回 oldValue 按位取反的结果。结果为 32位 有符号整数。

逻辑非运算符

产生式 ** : ! ** 按照下面的过程执行 :

  1. expr 为解释执行 ** 的结果。
  2. oldValueToBoolean(GetValue(expr))。
  3. 如果 oldValuetrue,返回 false
  4. 返回 true

乘法运算符

   MultiplicativeExpression :        **         *          /          % 

产生式 ** : ** @ **,其中 @ 表示上面定义的运算符其一,按照下面的过程执行:

  1. left 为解释执行 ** 的结果。
  2. leftValueGetValue(left)。
  3. right 为解释执行 ** 的结果。
  4. rightValueGetValue(right)。
  5. leftNumToNumber(leftValue)。
  6. rightNumToNumber(rightValue)。
  7. 返回将特定运算符 (*, /%) 作用于 leftNumrightNum 的结果。参见 11.5.111.5.211.5.3 后的注解。

使用 * 运算符

* 运算符表示乘法,产生操作数的乘积。乘法运算满足交换律。因为精度问题,乘法不总是满足结合律。

浮点数的乘法遵循 IEEE 754 二进制双精度幅度浮点算法规则:

  • 若两个操作数之一为 NaN,结果为 NaN
  • 假如两个操作数的正负号相同,结果就是正的,如果不同就是负的。
  • 无穷大被零乘结果是 NaN
  • 无穷大被无穷大乘结果就是无穷大。符号按照前面说过的规则决定。
  • 无穷大被有穷的非零值乘结果是带正负号的无穷大。符号仍然按照前面说过的规则决定。
  • 其它情况下,既没有无穷大也没有 NaN 参与运算,结果计算出来后会按照 IEEE 754 round-to-nearest 取到最接近的能表示的数。如果值过大不能表示,则结果为相应的正负无穷大。如果值过小不能表示,则结果为相应的正负零。ECMAScript 要求支持 IEEE 754 规定的渐进下溢。

使用 / 运算符

/ 运算符表示除法,产生操作数的商。左操作数是被除数,右操作数是除数。ECMAScript 不支持整数除法。所有除法运算的操作数和结果都是双精度浮点数。浮点数的除法遵循 IEEE 754 二进制双精度幅度浮点算法规则:

  • 若两个操作数之一为 NaN,结果为 NaN
  • 假如两个操作数的正负号相同,结果就是正的,如果不同就是负的。
  • 无穷大被无穷大除结果是 NaN
  • 无穷大被零除结果是无穷大。符号按照前面说过的规则决定。
  • 无穷大被非零有穷的值除结果是有正负号的无穷大。符号按照前面说过的规则决定。
  • 有穷的非零值被无穷大除结果是零。符号按照前面说过的规则决定。
  • 零被零除结果是 NaN;零被其它有穷数除结果是零,符号按照前面说过的规则决定。
  • 有穷的非零值被零除结果是有正负号的无穷大。符号按照前面说过的规则决定。
  • 其它情况下,既没有无穷大也没有 NaN 参与运算,结果计算出来后会按照 IEEE 754 round-to-nearest 取到最接近的能表示的数。如果值过大不能表示,则结果为相应的正负无穷大。如果值过小不能表示,则结果为相应的正负零。ECMAScript 要求支持 IEEE 754 规定的渐进下溢。

使用 % 运算符

% 运算符产生其运算符在除法中的余数。左操作数是被除数,右操作数是除数。

浮点数使用 % 运算符的余数运算与 IEEE 754 所定义的 “remainder” 运算不完全相同。IEEE 754 “remainder” 运算做邻近取整除法的余数计算,而不是舍尾除法,这样它的行为跟通常意义上的整数余数运算符行为不一致。而 ECMAScript 语言定义浮点操作 % 为与 Java 取余运算符一致;可以参照 C 库中的函数 fmod。

ECMAScript 浮点数的取余法遵循 IEEE 754 二进制双精度幅度浮点算法规则:

  • 若两个操作数之一为 NaN,结果为 NaN
  • 结果的符号等于被除数。
  • 若被除数是无穷大或者除数是零,或者两者皆是,结果就是 NaN
  • 若被除数有穷而除数为无穷大,结果为被除数。
  • 若被除数为零且除数非零且有穷,结果与被除数相同。
  • 其它情况下,既没有零或无穷大,也没有 NaN 参与运算,从被除数 n 和除数 d 得到浮点数余数 r 以数学关系式 r = n ? (d × q) 定义,其中 q 是个整数,在 n / d 为负时为负,在 n / d 为正时为正,它应该在不超过 nd 的商的前提下尽可能大。结果计算出来后会按照 IEEE 754 round-to-nearest 取到最接近的能表示的数。

加法运算符

   AdditiveExpression :        **         +          - 

加法运算符(+)

加法运算符启动字符串相接或是数值相加。

产生式 ** : ** + ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。

  2. lvalGetValue(lref)。

  3. rref 为解释执行 ** 的结果。

  4. rvalGetValue(rref)。

  5. lprimToPrimitive(lval)。

  6. rprimToPrimitive(rval)。

  7. 如果 Type(lprim) 为 String 或者 Type(rprim) 为 String,则:

    1. 返回由 ToString(lprim) 和 ToString(rprim) 连接而成的字符串。
  8. 返回将加法运算作用于 ToNumber(lprim) 和 ToNumber(rprim) 的结果。参见 11.6.3 后的注解。

减法运算符(-)

产生式 ** : ** - ** 按照下面的过程执行 :

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. lnumToNumber(lval)。
  6. rnumToNumber(rval)。
  7. 返回返回将减法运算作用于 lnumrnum 的结果。参见 11.6.3 后的注解。

加法作用于数字

+ 运算符作用于两个数字类型的操作数时表示加法,产生两个操作数之和。- 运算符表示剑法,产生两个数字之差。

加法是满足交换律的运算,但是不总满足结合律。

加法遵循 IEEE 754 二进制双精度幅度浮点算法规则:

  • 若两个操作数之一为 NaN,结果为 NaN
  • 两个正负号相反的无穷之和为 NaN
  • 两个正负号相同的无穷大之和是具有相同正负的无穷大。
  • 无穷大和有穷值之和等于操作数中的无穷大。
  • 两个负零之和为 -0
  • 两个正零,或者两个正负号相反的零之和为 +0
  • 零与非零有穷值之和等于非零的那个操作数。
  • 两个大小相等,符号相反的非零有穷值之和为 +0
  • 其它情况下,既没有无穷大也没有 NaN 或者零参与运算,并且操作数要么大小不等,要么符号相同,结果计算出来后会按照 IEEE 754 round-to-nearest 取到最接近的能表示的数。如果值过大不能表示,则结果为相应的正负无穷大。如果值过小不能表示,则结果为相应的正负零。ECMAScript 要求支持 IEEE 754 规定的渐进下溢。

- 运算符作用于两个数字类型时表示减法,产生两个操作数之差。左边操作数是被减数右边是减数。给定操作数 ab,总是有 ab 产生与 a + (-b) 产生相同结果。

移位运算符

   ShiftExpression :        **         <<          >>          >>> 

左移位运算符(<<)

对左边参数执行右边参数指定大小的左移位运算。

产生式 ** : ** << ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. lnumToInt32(lval)。
  6. rnumToUint32(rval)。
  7. shiftCount 为用掩码算出 rnum 的最后五个比特位,即计算 rnum & 0x1F 的结果。
  8. 返回 lnum 左移 shiftCount 比特位的结果。结果是一个有符号 32位 整数。

带号右移位运算符(>>)

对左边参数执行右边参数指定大小的右移位带号填充运算。

产生式 ** : ** >> ** 按照下面的过程执行 :

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. lnumToInt32(lval)。
  6. rnumToUint32(rval)。
  7. shiftCount 为用掩码算出 rnum 的最后五个比特位,即计算 rnum & 0x1F 的结果。
  8. 返回 lnum 带符号扩展的右移 shiftCount 比特位的结果。将位用最大的比特填满。结果是一个有符号 32位 整数。

不带号右移位运算符(>>>)

对左边参数执行右边参数指定大小的右移位填零运算。

产生式 ** : ** >>> ** 按照下面的过程执行 :

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. lnumToUint32(lval)。
  6. rnumToUint32(rval)。
  7. shiftCount 为用掩码算出 rnum 的最后五个比特位,即计算 rnum & 0x1F 的结果。
  8. 返回 lnum 做零填充右移 shiftCount 比特位的结果。缺少的比特位填零。结果是一个无符号 32位 整数。

关系运算符

   RelationalExpression :        **         <          >          <=          >=          instanceof          in 

   RelationalExpressionNoIn :        **         <          >          <=          >=          instanceof 

关系运算符的执行结果总是一个表示运算符代表的关系在两个参数之间成立与否的 Boolean 值。

除了要执行内有的 ** 而不是** 以外,产生式 ** 的执行方式与产生式 ** 的执行方式相同。

小于运算符(>)

产生式 ** : ** < ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. r 为启用抽象关系比较 lval < rval(参见 11.8.5) 的结果。
  6. 如果 rundefined,返回 false。否则,返回 r

大于运算符(>)

产生式 ** : ** > ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. r 为启用抽象关系比较 rval < lval 的结果,参数 LeftFirst 设为 false。(参见 11.8.5)
  6. 如果 rundefined,返回 false。否则,返回 r

=== 小于等于运算符(<=) ===

产生式 ** : ** <= ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. r 为启用抽象关系比较 rval < lval 的结果,参数 LeftFirst 设为 false。(参见 11.8.5)
  6. 如果 rtrue 或者 undefined ,返回 false。否则,返回 true

=== 大于等于运算符(>=) ===

产生式 ** : ** >= ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. r 为启用抽象关系比较 lval < rval 的结果。(参见 11.8.5)
  6. 如果 rtrue 或者 undefined,返回 false。否则,返回 true

抽象关系比较算法

xy 为值进行小于比较(x < y 的比较),会产生的结果可为 truefalseundefined(这说明 xy 中最少有一个操作数是 NaN)。除了 xy,这个算法另外需要一个名为 LeftFirst 的布尔值标记作为参数。这个标记用于解析顺序的控制,因为操作数 xy 在执行的时候会有潜在可见的副作用。这个标志的存在是必须的,因为 ECMAScript 规定了表达式是从左到右顺序执行。LeftFirst 的默认值是 true,这表明在相关的表达式中,参数 x 出现在参数 y 之前。如果 LeftFirst 值是 false,情况会相反,操作数的执行必须是先 yx。这样的一个小于比较的执行步骤如下:

  1. 如果 LeftFirst 标志是 true,那么

    1. px 为调用 ToPrimitive(x, 暗示 Number 类型) 的结果。
    2. py 为调用 ToPrimitive(y, 暗示 Number 类型) 的结果。
  2. 否则解释执行的顺序需要反转,从而保证从左到右的执行顺序

    1. py 为调用 ToPrimitive(y, 暗示 Number 类型) 的结果。
    2. px 为调用 ToPrimitive(x, 暗示 Number 类型) 的结果。
  3. 如果 Type(px) 和 Type(py) 得到的结果不都是 String 类型,那么

    1. nx 为调用 ToNumber(px) 的结果。因为 pxpy 都已经是基本数据类型(primitive values 也作原始值),其执行顺序并不重要。
    2. ny 为调用 ToNumber(py) 的结果。
    3. 如果 nxNaN,返回 undefined
    4. 如果 nyNaN,返回 undefined
    5. 如果 nxny 的数字值相同,返回 false
    6. 如果 nx+0ny-0,返回 flase
    7. 如果 nx-0ny+0,返回 false
    8. 如果 nx+∞,返回 fasle
    9. 如果 ny+∞,返回 true
    10. 如果 ny-∞,返回 false
    11. 如果 nx-∞,返回 true
    12. 如果 nx 数学上的值小于 ny 数学上的值(注意这些数学值都不能是无限的且不能都为 0),返回 ture。否则返回 false
  4. 否则,pxpy 都是 Strings 类型

    1. 如果 pypx 的一个前缀,返回 false。(当字符串 q 的值可以是字符串 p 和一个其他的字符串 r 拼接而成时,字符串 p 就是 q 的前缀。注意:任何字符串都是自己的前缀,因为 r 可能是空字符串。)
    2. 如果 pxpy 的前缀,返回 true
    3. k 成为最小的非负整数,能使得在 px 字符串中位置 k 的字符与字符串 py 字符串中位置 k 的字符不相同。(因为 pxpy 不是彼此的前綴,这里 k 必然存在。)
    4. m 为字符串 px 中位置 k 的字符的编码单元值。
    5. n 成为字符串 py 中位置 k 的字符的编码单元值。
    6. 如果 m < n,返回 true。否则,返回 false

instanceof 运算符

产生式 **: ** instanceof ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. 如果 Type(rval) 不是 Object,抛出一个 TypeError 异常。
  6. 如果 rval 没有 [[HasInstance]] 内置方法,抛出一个 TypeError 异常。
  7. 返回以参数 lval 调用 rval[[HasInstance]] 内置方法的结果。

in 运算符

产生式 ** : ** in ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. 如果 Type(rval) 不是 Object,抛出一个 TypeError 异常。
  6. 返回以参数 ToString(lval) 调用 rval[[HasProperty]] 内置方法的结果。

等值运算符

   EqualityExpression :        **         ==          !=          ===          !== 

   EqualityExpressionNoIn :        **         ==          !=          ===          !== 

等值运算符的执行结果总是一个表示运算符代表的关系在两个参数之间成立与否的 Boolean 值。

除了要执行内有的 ** 与 ** 而不是** 与 ** 以外,产生式 ** 的执行方式与产生式 ** 的执行方式相同。

=== 等于运算符(==) ===

产生式 ** : ** == ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. 返回做用抽象相等比较算法于 rval == lval(参见 11.9.3)的结果。

=== 不等于运算符(!=) ===

产生式 ** : ** != ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. r 为做用抽象相等比较算法于 rval == lval(参见 11.9.3)的结果。
  6. 如果 rtrue,返回 false。否则,返回 true

抽象相等比较算法

xy 为值进行 x == y 比较会产生的结果可为 truefalse。比较的执行步骤如下:

  1. Type(x) 与 Type(y) 相同, 则

    1. Type(x) 为 Undefined, 返回 true

    2. Type(x)为 Null, 返回 true

    3. Type(x)为 Number,则

      1. xNaN,返回 false
      2. yNaN,返回 false
      3. xy 为相等数值,返回 true
      4. x+0y?0,返回 true
      5. x?0y+0,返回 true
      6. 返回 false
    4. Type(x) 为 String,则当 xy 为完全相同的字符序列(长度相等且相同字符在相同位置)时返回 true。否则,返回 false

    5. Type(x) 为 Boolean,当 xy 为同为 true 或者同为 false 时返回 true。否则,返回 false

    6. xy 为引用同一对象时返回 true。否则,返回 false

  2. xnullyundefined,返回 true

  3. xundefinedynull,返回 true

  4. Type(x) 为 NumberType(y) 为 String,返回 x == ToNumber(y) 的结果。

  5. Type(x) 为 StringType(y) 为 Number,返回比较 ToNumber(x) == y 的结果。

  6. Type(x) 为 Boolean,返回比较 ToNumber(x) == y 的结果。

  7. Type(y) 为 Boolean,返回比较 x == ToNumber(y) 的结果。

  8. Type(x) 为 StringNumber,且 Type(y) 为 Object,返回比较 x == ToPrimitive(y) 的结果。

  9. Type(x) 为 ObjectType(y) 为 StringNumber,返回比较 ToPrimitive(x) == y 的结果。

  10. 返回 false

严格等于运算符(

) ===

产生式 ** : ** === ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. 返回做用严格等于比较算法于 rval === lval(参见 11.9.6)的结果。

=== 严格不等于运算符(!==) ===

产生式 ** : ** !== ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. rvalGetValue(rref)。
  5. r 为做用严格等于比较算法于 rval === lval(参见 11.9.6)的结果。
  6. 如果 rtrue,返回 false。否则,返回 true

严格等于比较算法

比较 x === yxy 为值,需要产出 truefalse。比较过程如下:

  1. 如果 Type(x) 与 Type(y) 的结果不一致,返回 false

  2. 如果 Type(x) 结果为 Undefined,返回 true

  3. 如果 Type(x) 结果为 Null,返回 true

  4. 如果 Type(x) 结果为 Number,则

    1. 如果 xNaN,返回 false
    2. 如果 yNaN,返回 false
    3. 如果 xy 为同一个数字,返回 true
    4. 如果 x+0y-0,返回 true
    5. 如果 x-0y+0,返回 true
    6. 返回 false
  5. 如果 Type(x) 结果为 String,如果 xy 为完全相同的字符序列(相同的长度和相同的字符对应相同的位置),返回 true,否则,返回 false

  6. 如果 Type(x) 结果为 Boolean,如果 xy 都为 truefalse,则返回 true,否则,返回 false

  7. 如果 xy 引用到同一个 Object 对象,返回 true,否则,返回 false

二元按位运算符

   BitwiseANDExpression :        **         & 

   BitwiseANDExpressionNoIn :        **         & 

   BitwiseXORExpression :        **         ^ 

   BitwiseXORExpressionNoIn :        **         ^ 

   BitwiseORExpression :        **         | 

   BitwiseORExpressionNoIn :        **         | 

产生式 A : A @ B,其中 @ 是上述产生式中其中一个位运算符,按照下面的过程执行:

  1. lref 为解释执行 A 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 B 的结果。
  4. rvalGetValue(rref)。
  5. lnumToInt32(lval)。
  6. rnumToInt32(rval)。
  7. 返回作用位运算符 @ 作用到 lnumrnum 的结果,是一个 32位 有符号整数。

二元逻辑运算符

   LogicalANDExpression :        **         && 

   LogicalANDExpressionNoIn :        **         && 

   LogicalORExpression :        **         || 

   LogicalORExpressionNoIn :        **         || 

产生式 ** : ** && ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. 如果 ToBoolean(lval) 为 false,返回 lval
  4. rref 为解释执行 ** 的结果。
  5. 返回 GetValue(rref)。

产生式 ** : ** || ** 按照下面的过程执行 :

  1. lref 为解释执行 ** 的结果。
  2. lvalGetValue(lref)。
  3. 如果 ToBoolean(lval) 为 true,返回 lval
  4. rref 为解释执行 ** 的结果。
  5. 返回 GetValue(rref)。

除了要执行内有的 与 ** 而不是**、** 与 ** 以外,产生式 ** 与 ** 的执行方式与产生式 ** 与 ** 的执行方式相同。

条件运算符

   ConditionalExpression :        **         ?  : **

   ConditionalExpressionNoIn :        **         ?  : **

产生式 ** : ** ? ** : ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。

  2. 如果 ToBoolean(GetValue(lref)) 为 true,那么:

    1. trueRef 为解释执行第一个 ** 的结果。
    2. 返回 GetValue(trueRef)。
  3. 否则

    1. falseRef 为解释执行第二个 ** 的结果。
    2. 返回 GetValue(falseRef)。

除了要执行内有的 与 ** 而不是**、** 与 ** 以外,产生式 ** 的执行方式与产生式 ** 的执行方式相同。

赋值运算符

   AssignmentExpression :        **          **

   AssignmentExpressionNoIn :        **          **

   AssignmentOperator : 以下之一         = *= /= %= += -= <<= >>= >>>= &= ^= |= 

除了要执行内有的 ** 与 ** 而不是** 与 ** 以外,产生式 ** 的执行方式与产生式 ** 的执行方式相同。

=== 简单赋值(=) ===

产生式 ** : ** = ** 按照下面的过程执行 :

  1. lref 为解释执行 ** 的结果。

  2. rref 为解释执行 ** 的结果。

  3. rvalGetValue(rref)。

  4. 抛出一个 SyntaxError 异常,当以下条件都成立 :

  5. 调用 PutValue(lref, rval)。

  6. 返回 rval

=== 组合赋值(op=) ===

产生式 ** : ** @= **,其中 @ 表示上述的运算符其一,按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。

  2. lvalGetValue(lref)。

  3. rref 为解释执行 ** 的结果。

  4. rvalGetValue(rref)。

  5. r 为作用运算符 @ 于 lvalrval 的结果。

  6. 抛出一个 SyntaxError 异常,当以下条件都成立 :

  7. 调用 PutValue(lref, r)。

  8. 返回 r

逗号运算符

   Expression :        **         , 

   ExpressionNoIn :        **         , 

产生式 ** : ** , ** 按照下面的过程执行:

  1. lref 为解释执行 ** 的结果。
  2. 调用 GetValue(lref)。
  3. rref 为解释执行 ** 的结果。
  4. 返回 GetValue(rref)。

除了要执行内有的 ** 与 ** 而不是 ** 与 ** 以外,产生式 ** 的执行方式与产生式 ** 的执行方式相同。