ES5/表达式

From HTML5 Chinese Interest Group Wiki
< ES5
Jump to: navigation, search

主值表达式



语法:

   PrimaryExpression :
       this 
       Identifier
       Literal
       ArrayLiteral
       ObjectLiteral
       ( Expression )

this关键字V8.png

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

标识符引用 V8.png

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

字面量引用 V8.png V8.png

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

数组初始化 V8.png

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

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

语法:

   ArrayLiteral :
       [ Elisionopt ]
       [ ElementList ]
       [ ElementList , Elisionopt ]
   ElementList :
       Elisionopt AssignmentExpression
       ElementList , Elisionopt AssignmentExpression
   Elision :
       ,
       Elision ,

语义:

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

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

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

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

产生式 ArrayLiteral : [ ElementList , Elisionopt ] 按照下面的过程执行:

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

产生式 ElementList : Elisionopt AssignmentExpression 按照下面的过程执行 :

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

产生式 ElementList : ElementList , Elisionopt AssignmentExpression 按照下面的过程执行 :

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

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

  1. 返回数值 1

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

  1. preceding 为解释执行 Elision 的结果。
  2. 返回 preceding+1
注:[[DefineOwnProperty]] 用于确保即使默认的数组原型对象被更改的情况下自身属性也会被定义,可以杜绝用 [[Put]] 创建一个新的自身属性。

对象初始化 V8.png

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

语法:

   ObjectLiteral :
       { } 
       { PropertyNameAndValueList }
       { PropertyNameAndValueList , }
   PropertyNameAndValueList :
       PropertyAssignment
       PropertyNameAndValueList , PropertyAssignment
   PropertyAssignment :
       PropertyName : AssignmentExpression
       get PropertyName ( ) { FunctionBody }
       set PropertyName ( PropertySetParameterList ) { FunctionBody }
   PropertyName :
       IdentifierName
       StringLiteral
       NumericLiteral
   PropertySetParameterList :
       Identifier

语义:

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

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

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

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

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

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

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

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

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

产生式 PropertyAssignment : PropertyName : AssignmentExpression 按照下面的过程执行 :

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

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

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

产生式 PropertyAssignment : set PropertyName ( PropertySetParameterList ) { FunctionBody } 按照下面的过程执行:

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

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

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

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

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

  1. 返回 StringLiteral 的字符串值。

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

  1. nbr 为求 NumericLiteral 值的结果。
  2. 返回 ToString(nbr)。
注:[[DefineOwnProperty]] 用于确保即使在内置的 Array.prototype 被修改的情况下数组的自身属性也会被定义,这可以避免用 [[Put]] 来创建新的自身属性。

群组运算符 V8.png

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

  1. 返回执行 Expression 的结果。这可能是一个 Reference
注:本算法不在执行 Expression 后使用 GetValue。这主要的目的是让 deletetypeof 运算符可以作用在被括号括起来的表达式。

左值表达式



语法:

   MemberExpression :
       PrimaryExpression
       FunctionExpression
       MemberExpression [ Expression ]
       MemberExpression . IdentifierName
       new MemberExpression Arguments
   NewExpression :
       MemberExpression
       new NewExpression
   CallExpression :
       MemberExpression Arguments
       CallExpression Arguments
       CallExpression [ Expression ]
       CallExpression . IdentifierName
   Arguments :
       ( )
       ( ArgumentList )
   ArgumentList :
       AssignmentExpression
       ArgumentList , AssignmentExpression
   LeftHandSideExpression :
       NewExpression
       CallExpression

属性访问 V8.png

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

   MemberExpression . IdentifierName
   CallExpression . IdentifierName

或者括号表示法访问

   MemberExpression [ Expression ] 
   CallExpression [ Expression ]

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

   MemberExpression . IdentifierName

这会等同于下面这个行为

   MemberExpression [ <identifier-name-string> ]

类似地,

   CallExpression . IdentifierName

是等同于下面的行为

   CallExpression [ <identifier-name-string> ]

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

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

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

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

new 运算符 V8.png

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

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

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

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

函数调用 V8.png


产生式 CallExpression : MemberExpression Arguments 按照下面的过程执行 :

  1. ref 为解释执行 MemberExpression 的结果。
  2. funcGetValue(ref)。
  3. argList 为解释执行 Arguments 的结果,产生参数值们的内部列表(参见 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 作为参数列表。

参数列表 V8.png

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

  1. 返回一个空列表

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

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

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

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

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

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

函数表达式 V8.png

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

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

后缀表达式 V8.png



语法:

   PostfixExpression :
       LeftHandSideExpression
       LeftHandSideExpression [no LineTerminator here] ++ 
       LeftHandSideExpression [no LineTerminator here] --

后缀自增运算符

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

  1. lhs 为解释执行 LeftHandSideExpression 的结果。
  2. 假如以下所有条件都为真,抛出一个 SyntaxError 异常:
  3. oldValueToNumer(GetValue(lhs))。
  4. newValue1 加上 oldValue 的结果,使用与 + 运算符 相同的规则(参见 11.6.3)。
  5. 调用 PutValue(lhs, newValue)。
  6. 返回 oldValue

后缀自减运算符

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

  1. lhs 为解释执行 LeftHandSideExpression 的结果。
  2. 假如以下所有条件都为真,抛出一个 SyntaxError 异常:
  3. oldValueToNumer(GetValue(lhs))。
  4. newValue 为从 oldValue 减掉 1 的结果,使用与 - 运算符 相同的规则(参见 11.6.3)。
  5. 调用 PutValue(lhs, newValue)。
  6. 返回 oldValue

一元运算符 V8.png



语法:

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

delete 运算符 V8.png

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

  1. ref 为解释执行 UnaryExpression 的结果。
  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 具体方法的结果。
注:当 delete 操作符在严格模式下出现时,并且 UnaryExpression 是一个变量、函数参数或者函数名的直接引用,则抛出 SyntaxError 异常。此外,严格模式下删除属性且其内置属性 [[Configurable]]false 时,则抛出 TypeError 异常。 V8.png

void 运算符

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

  1. expr 为解释执行 UnaryExpression 的结果。
  2. 调用 GetValue(expr)。
  3. 返回 undefined
注:就算值不会用到,用户代理仍必须调用 GetValue,因为可能有可观测的副作用。

typeof 运算符 V8.png

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

  1. val 为解释执行 UnaryExpression 的结果。
  2. 如果 Type(val) 为 Reference,则:
    1. 如果 IsUnresolvableReference(val) 为 true,返回 "undefined"
    2. valGetValue(val)。
  3. 返回根据 表20Type(val) 决定的字符串。V8.png
表20 typeof 运算符结果
val 类型 结果
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
Object(原生,且没有实现 [[Call]] "object"
Object(原生或者宿主且实现了 [[Call]] "function"
Object(宿主且没实现 [[Call]] 由实现定义,但不能是 "undefined""boolean""number""string"

前自增运算符 V8.png

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

  1. expr 为解释执行 UnaryExpression 的结果。
  2. 假如以下所有条件都为真,抛出一个 SyntaxError 异常:
  3. oldValueToNumer(GetValue(expr))。
  4. newValue1 加上 oldValue 的结果,使用与 + 运算符 相同的规则(参见 11.6.3)。
  5. 调用 PutValue(expr, newValue)。
  6. 返回 newValue

前自减运算符 V8.png

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

  1. expr 为解释执行 UnaryExpression 的结果。
  2. 假如以下所有条件都为真,抛出一个 SyntaxError 异常:
  3. oldValueToNumer(GetValue(expr))。
  4. newValue 为从 oldValue 减掉 1 的结果,使用与 - 运算符 相同的规则(参见 11.6.3)。
  5. 调用 PutValue(expr, newValue)。
  6. 返回 newValue

一元 + 运算符 V8.png

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

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

一元 - 运算符 V8.png

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

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

按位非运算符 V8.png

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

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

逻辑非运算符 V8.png

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

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

乘法运算符



语法:

   MultiplicativeExpression :
       UnaryExpression
       MultiplicativeExpression * UnaryExpression
       MultiplicativeExpression / UnaryExpression
       MultiplicativeExpression % UnaryExpression

语义:

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

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

使用 * 运算符 V8.png

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

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

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

使用 / 运算符 V8.png

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

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

使用 % 运算符 V8.png

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

注:在 C 和 C++ 中,余数运算符只接受整数为操作数;在 ECMAScript,它还接受浮点操作数。

浮点数使用 % 运算符的余数运算与 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 :
       MultiplicativeExpression
       AdditiveExpression + MultiplicativeExpression
       AdditiveExpression - MultiplicativeExpression

加法运算符(+) V8.png

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

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

  1. lref 为解释执行 AdditiveExpression 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 MultiplicativeExpression 的结果。
  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 后的注解。
注:在 第5步第6步ToPrimitive 的调用没有提供暗示类型。所有除了 Date 对象的 ECMAScript 原生对象会在没有提示的时候假设提示是 NumberDate 对象会假设提示是 String。宿主对象可以假设提示是任何东西。
注:第7步 与关系比较算法的 第3步 不同(11.8.5),使用逻辑 “或” 而不是 “与”。

减法运算符(-) V8.png

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

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

加法作用于数字 V8.png

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

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

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

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

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

移位运算符



语法:

   ShiftExpression :
       AdditiveExpression
       ShiftExpression << AdditiveExpression
       ShiftExpression >> AdditiveExpression
       ShiftExpression >>> AdditiveExpression

左移位运算符(<<) V8.png

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

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

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

带号右移位运算符(>>) V8.png

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

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

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

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

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

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

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

关系运算符



语法:

   RelationalExpression :
       ShiftExpression
       RelationalExpression < ShiftExpression
       RelationalExpression > ShiftExpression
       RelationalExpression <= ShiftExpression
       RelationalExpression >= ShiftExpression
       RelationalExpression instanceof ShiftExpression
       RelationalExpression in ShiftExpression
   RelationalExpressionNoIn :
       ShiftExpression
       RelationalExpressionNoIn < ShiftExpression
       RelationalExpressionNoIn > ShiftExpression
       RelationalExpressionNoIn <= ShiftExpression
       RelationalExpressionNoIn >= ShiftExpression
       RelationalExpressionNoIn instanceof ShiftExpression
注:“NoIn” 变种的存在是为了要避免把一个关系表达式里的 in 和一个 for语句 里的 in 搞混。

语义:

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

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

小于运算符(>)

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

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

大于运算符(>)

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

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

小于等于运算符(<=)

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

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

大于等于运算符(>=)

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

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

抽象关系比较算法 V8.png V8.png

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
注:使用或代替的时候要注意,这里的 第3步 和加号操作符 + 算法(11.6.1)的 第7步 的区别。
注:String 类型的比较使用了其编码单元值的作为一个简单的词法表序列去比较。这里不打算使用更复杂的、语义化的字符或字符串序列,和 Unicode 规范的整理序列进行比较。因此,字符串的值和其对应的 Unicode 标准的值是不相同的。实际上,这个算法假定了所有字符串已经是正常化的格式。同时要注意,对于字符串拼接追加的字符的时候,UTF-16 编码单元值的词法表序列是不同于代码点值的序列的。

instanceof 运算符 V8.png V8.png

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

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

in 运算符 V8.png V8.png

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

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

等值运算符



语法:

   EqualityExpression :
       RelationalExpression
       EqualityExpression == RelationalExpression
       EqualityExpression != RelationalExpression
       EqualityExpression === RelationalExpression
       EqualityExpression !== RelationalExpression
   EqualityExpressionNoIn :
       RelationalExpressionNoIn
       EqualityExpressionNoIn == RelationalExpressionNoIn
       EqualityExpressionNoIn != RelationalExpressionNoIn
       EqualityExpressionNoIn === RelationalExpressionNoIn
       EqualityExpressionNoIn !== RelationalExpressionNoIn

语义:

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

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

等于运算符(==)

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

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

不等于运算符(!=)

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

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

抽象相等比较算法 V8.png

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
注:根据上述等于的定义:
  • 字符串比较可以以:"" + a == "" + b 硬性触发。
  • 数值比较可以以:+a == +b 硬性触发。
  • 布尔比较可以以:!a == !b 硬性触发。
注:等于运算符有以下的不变量:
  • A != B!(A == B) 相等。
  • 除了 AB 的执行顺序以外,A == BB == A 相等。
注:等于运算符不总是可传递。举例来说,两个代表相同 String 值但是不同的 String 对象会分别与 String==,但是两个对象间不相等。
注:String 的比较使用代码单元序列的简单等号比较。这里不打算使用更复杂的、语义化的字符或字符串序列,和 Unicode 规范的整理序列进行比较。因此,在 Unicode 标准中相等的 String 值可能在本算法中不相等。也就是,这个算法假定了所有字符串已经正规化。

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

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

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

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

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

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

严格等于比较算法 V8.png

比较 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
注: 此算法与 SameValue (9.12) 算法在对待 有符号零NaN 上表现不同。

二元按位运算符



语法:

   BitwiseANDExpression :
       EqualityExpression
       BitwiseANDExpression & EqualityExpression
   BitwiseANDExpressionNoIn :
       EqualityExpressionNoIn
       BitwiseANDExpressionNoIn & EqualityExpressionNoIn
   BitwiseXORExpression :
       BitwiseANDExpression
       BitwiseXORExpression ^ BitwiseANDExpression
   BitwiseXORExpressionNoIn :
       BitwiseANDExpressionNoIn
       BitwiseXORExpressionNoIn ^ BitwiseANDExpressionNoIn
   BitwiseORExpression :
       BitwiseXORExpression
       BitwiseORExpression | BitwiseXORExpression
   BitwiseORExpressionNoIn :
       BitwiseXORExpressionNoIn
       BitwiseORExpressionNoIn | BitwiseXORExpressionNoIn

语义:

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

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

二元逻辑运算符



语法:

   LogicalANDExpression :
       BitwiseORExpression
       LogicalANDExpression && BitwiseORExpression
   LogicalANDExpressionNoIn :
       BitwiseORExpressionNoIn
       LogicalANDExpressionNoIn && BitwiseORExpressionNoIn
   LogicalORExpression :
       LogicalANDExpression
       LogicalORExpression || LogicalANDExpression
   LogicalORExpressionNoIn :
       LogicalANDExpressionNoIn
       LogicalORExpressionNoIn || LogicalANDExpressionNoIn

语义:

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

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

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

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

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

注:&&|| 运算符产生的值不一定是布尔值。产生的值总是两个表达式其一。

条件运算符 V8.png



语法:

   ConditionalExpression :
       LogicalORExpression
       LogicalORExpression ? AssignmentExpression : AssignmentExpression
   ConditionalExpressionNoIn :
       LogicalORExpressionNoIn
       LogicalORExpressionNoIn ? AssignmentExpressionNoIn : AssignmentExpressionNoIn

语义:

产生式 ConditionalExpression : LogicalORExpression ? AssignmentExpression : AssignmentExpression 按照下面的过程执行:

  1. lref 为解释执行 LogicalORExpression 的结果。
  2. 如果 ToBoolean(GetValue(lref)) 为 true,那么:
    1. trueRef 为解释执行第一个 AssignmentExpression 的结果。
    2. 返回 GetValue(trueRef)。
  3. 否则
    1. falseRef 为解释执行第二个 AssignmentExpression 的结果。
    2. 返回 GetValue(falseRef)。

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

注:在 ECMAScript 里 ConditionalExpression 的语法与 C、Java 的语法有一点不同,C、Java 允许第二个子表达式可以是任意的 Expression 但是限制第三个表达式必须是 ConditionalExpression。ECMAScript 在这里不同的理由是让两支条件都可以使用赋值表达式并消除既无用解析又困难的情形:在中间的表达式使用逗号表达式。

赋值运算符 V8.png



语法:

   AssignmentExpression :
       ConditionalExpression
       LeftHandSideExpression AssignmentOperator AssignmentExpression
   AssignmentExpressionNoIn :
       ConditionalExpressionNoIn
       LeftHandSideExpression AssignmentOperator AssignmentExpressionNoIn
   AssignmentOperator : 以下之一 
       = *= /= %= += -= <<= >>= >>>= &= ^= |= 

语义:

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

简单赋值(=)

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

  1. lref 为解释执行 LeftHandSideExpression 的结果。
  2. rref 为解释执行 AssignmentExpression 的结果。
  3. rvalGetValue(rref)。
  4. 抛出一个 SyntaxError 异常,当以下条件都成立 :
  5. 调用 PutValue(lref, rval)。
  6. 返回 rval
注:当赋值出现在严格模式代码的时候,赋值的 LeftHandSideExpression 必须不被解释执行为一个不可解析的引用。若这种情形发生,则赋值的时候用户代理会抛出 ReferenceError 例外。LeftHandSideExpression 也不可以是一个特性值是 {[[Writable]]: false} 的数据属性,或是特性值是 {[[Set]]: undefined} 的访问器属性,或是 [[Extensible]] 内部属性是 false 的对象尚未存在的属性引用。在这些情况下用户代理会抛出 TypeError 异常。

组合赋值(op=)

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

  1. lref 为解释执行 LeftHandSideExpression 的结果。
  2. lvalGetValue(lref)。
  3. rref 为解释执行 AssignmentExpression 的结果。
  4. rvalGetValue(rref)。
  5. r 为作用运算符 @ 于 lvalrval 的结果。
  6. 抛出一个 SyntaxError 异常,当以下条件都成立 :
  7. 调用 PutValue(lref, r)。
  8. 返回 r
注:参见 11.13.1 的备注。

逗号运算符



语法:

   Expression :
       AssignmentExpression
       Expression , AssignmentExpression
   ExpressionNoIn :
       AssignmentExpressionNoIn
       ExpressionNoIn , AssignmentExpressionNoIn

语义:

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

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

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

注:就算值不会用到,用户代理仍必须调用 GetValue,因为可能有可观测的副作用。