- PrimaryExpression
**:** `this`

Identifier

Literal

ArrayLiteral

ObjectLiteral`(`

Expression`)`

`this`

Keyword`this`

keyword evaluates to the value of the ThisBinding of the current execution context.
(scroll to the next page)

© Ecma International 2009**62**

Array elements may be elided at the beginning, middle or end of the element list. Whenever a comma in the element list is not preceded by an

- ArrayLiteral
**:** `[`

Elision_{opt}`]`

ElementList

[`]`

ElementList

[`,`

Elision_{opt}`]`

- ElementList
**:** - Elision
_{opt}AssignmentExpression

ElementList`,`

Elision_{opt}AssignmentExpression

- Elision
**:** `,`

Elision`,`

The production

- Let
*array*be the result of creating a new object as if by the expression`new Array()`

where`Array`

is the standard built-in constructor with that name. - Let
*pad*be the result of evaluating*Elision*; if not present, use the numeric value zero. - Call the [[Put]] internal method of
*array*with arguments "`length`

",*pad*, and**false**. - Return .

- Return the result of evaluating
*ElementList*.

`,`

Elision- Let
*array*be the result of evaluating*ElementList*. - Let
*pad*be the result of evaluating*Elision*; if not present, use the numeric value zero. - Let
*len*be the result of calling the [[Get]] internal method of*array*with argument "length". - Call the [[Put]] internal method of
*array*with arguments "`length`

", ToUint32(*pad*+*len*), and**false**. - Return
*array*.

© Ecma International 2009**63**

- Let
*array*be the result of creating a new object as if by the expression`new Array()`

where`Array`

is the*standard*built-in constructor with that name. - Let
*firstIndex*be the result of evaluating*Elision*; if not present, use the numeric value zero. - Let
*initResult*be the result of evaluating*AssignmentExpression*. - Let
*initValue*be GetValue(*array*initResult). - Call the [[DefineOwnProperty]] internal method of
*array*with arguments ToString(*firstIndex*), the Property Descriptor { [[Value]]:*initValue*, [[Writable]]:**true**, [[Enumerable]]:**true**, [[Configurable]]:**true**}, and**false**. - Return
*array*.

- Let
*array*be the result of evaluating*ElementList*. - Let
*pad*be the result of evaluating*Elision*; if not present, use the numeric value zero. - Let
*initResult*be the result of evaluating*AssignmentExpression*. - Let
*initValue*be GetValue(*initResult*). - Let
*len*be the result of calling the [[Get]] internal method of*array*with argument "`length`

". - Call the [[DefineOwnProperty]] internal method of
*array*with arguments ToString(ToUint32((pad+len)) and the Property Descriptor { [[Value]]:*initValue*, [[Writable]]:**true**, [[Enumerable]]:**true**, [[Configurable]]:**true**}, and**false**. - Return
*array*.

`,`

is evaluated as follows:
- Return the numeric value 1.

`,`

is evaluated as follows:
- Let
*preceding*be the result of evaluating*Elision*. - Return
*preceding*+ 1.

NOTE [[DefineOwnProperty]] is used to ensure that own properties are defined for the array even if the standard
built-in Array prototype object has been modified in a manner that would preclude the creation of new own properties
using [[Put]].

- ObjectLiteral
**:** *{**}**{*PropertyNameAndValueList*}**{*PropertyNameAndValueList`,`

*}*

- PropertyNameAndValueList
**:** - PropertyAssignment

PropertyNameAndValueList`,`

PropertyAssignment

- PropertyAssignment
**:** - PropertyName
**:**AssignmentExpression

`get`

PropertyName*( )**{*FunctionBody*}*

`set`

PropertyName*(*PropertySetParameterList*)**{*FunctionBody*}*

© Ecma International 2009**64**

- PropertyName
**:** - IdentifierName

StringLiteral

NumericLiteral

- PropertySetParameterList
**:** - Identifier

The production

- Return a new object created as if by the expression
`new Object()`

where`Object`

is the standard builtin constructor with that name.

`,`

} are evaluated as follows:
- Return the result of evaluating
*PropertyNameAndValueList*.

- Let
*obj*be the result of creating a new object as if by the expression`new Object()`

where`Object`

is the standard built-in constructor with that name. - Let
*propId*be the result of evaluating*PropertyAssignment*. - Call the [[DefineOwnProperty]] internal method of
*obj*with arguments*propId*.name,*propId*.descriptor, and**false**. - Return
*obj*.

`,`

- Let
*obj*be the result of evaluating*PropertyNameAndValueList*. - Let
*propId*be the result of evaluating PropertyAssignment. - Let
*previous*be the result of calling the [[GetOwnProperty]] internal method of*obj*with argument*propId*.name. - If
*previous*is not**undefined**then throw a**SyntaxError**exception if any of the following conditions are true- This production is contained in strict code and IsDataDescriptor(
*previous*) is**true**and IsDataDescriptor(*propId*.descriptor) is**true**. - IsDataDescriptor(
*previous*) is**true**and IsAccessorDescriptor(*propId*.descriptor) is**true**. - IsAccessorDescriptor(
*previous*) is**true**and IsDataDescriptor(*propId*.descriptor) is**true**. - IsAccessorDescriptor(
*previous*) is**true**and IsAccessorDescriptor(*propId*.descriptor) is**true**and either both*previous*and propId.descriptor have [[Get]] fields or both*previous*and*propId*.descriptor have [[Set]] fields

- This production is contained in strict code and IsDataDescriptor(
- Call the [[DefineOwnProperty]] internal method of obj with arguments
*propId*.name,*propId*.descriptor, and**false**. - Return
*obj*.

- Let
*propName*be the result of evaluating PropertyName. - Let
*exprValue*be the result of evaluating AssignmentExpression. - Let
*propValue*be GetValue(exprValue). - Let
*desc*be the Property Descriptor{[[Value]]:*propValue*, [[Writable]]:**true**, [[Enumerable]]:**true**, [[Configurable]]:**true**} - Return Property Identifier (
*propName*,*desc*).

- Let
*preceding*be the result of evaluating*Elision*. - Return
*preceding*+ 1.

© Ecma International 2009**65**

The production *PropertyAssignment* : *PropertyName* ( ) { *FunctionBody* } is evaluated as follows:
*PropertyAssignment* : *PropertyName* ( *PropertySetParameterList* ) { *FunctionBody* } is
evaluated as follows:
**SyntaxError** if the *Identifier* "*Identifier* "*Identifier* in a
*PropertySetParameterList* of a *PropertyAssignment* that is contained in strict code or if its *FunctionBody* is strict code.

The production*PropertyName* : *IdentifierName* is evaluated as follows:
*PropertyName* : *StringLiteral* is evaluated as follows:
*PropertyName* : *NumericLiteral* is evaluated as follows:
### 11.1.6 The Grouping Operator

The production *PrimaryExpression* : ( *Expression* ) is evaluated as follows:
### 11.2 Left-Hand-Side Expressions

**Syntax**

`get`

- Let
*propName*be the result of evaluating*PropertyName*. - Let
*closure*be the result of creating a new Function object as specified in 13.2 with an empty parameter list and body specified by*FunctionBody*. Pass in the LexicalEnvironment of the running execution context as the*Scope*. Pass in**true**as the*Strict*flag if the*PropertyAssignment*is contained in strict code or if its*FunctionBody*is strict code. - Let
*desc*be the Property Descriptor{[[Get]]:*closure*, [[Enumerable]]:**true**, [[Configurable]]:**true**} - Return Property Identifier (
*propName*,*desc*).

`set`

- Let
*propName*be the result of evaluating*PropertyName*. - Let
*closure*be the result of creating a new*Function*object as specified in 13.2 with parameters specified by*PropertySetParameterList*and body specified by*FunctionBody*. Pass in the LexicalEnvironment of the running execution context as the*Scope*. Pass in**true**as the*Strict*flag if the*PropertyAssignment*is contained in strict code or if its*FunctionBody*is strict code. - Let
*desc*be the Property Descriptor{[[Set]]:*closure*, [[Enumerable]]:**true**, [[Configurable]]:**true**} - Return Property Identifier (
*propName*,*desc*).

`eval`

" or the `arguments`

" occurs as the The production

- Return the String value containing the same sequence of characters as the
*IdentifierName*.

- Return the SV of the
*StringLiteral*.

- Let
*nbr*be the result of forming the value of the*NumericLiteral*. - Return ToString(
*nbr*).

- Return the result of evaluating
*Expression*. This may be of type Reference.

NOTE This algorithm does not apply GetValue to the result of evaluating Expression. The principal motivation for this
is so that operators such as

`delete`

and `typeof`

may be applied to parenthesised expressions.- MemberExpression
**:** - PrimaryExpression

FunctionExpression

MemberExpression`[`

Expression`]`

MemberExpression . IdentifierName`new`

MemberExpression Arguments

© Ecma International 2009**66**

- MemberExpression
**:** - PrimaryExpression

FunctionExpression

MemberExpression`[`

Expression`]`

MemberExpression . IdentifierName`new`

MemberExpression Arguments

- NewExpression
**:** - MemberExpression
`new`

NewExpression

- CallExpression Arguments
- MemberExpression Arguments

CallExpression`[`

Expression`]`

CallExpression**.**IdentifierName

- Arguments
**:** *( )**(*ArgumentList*)*

- ArgumentList
**:** - AssignmentExpression

ArgumentList`,`

The production

- Let
*baseReference*be the result of evaluating*MemberExpression*. - Let
*baseValue*be GetValue(*baseReference*). - Let
*propertyNameReference*be the result of evaluating*Expression*. - Let
*propertyNameValue*be GetValue(*propertyNameReference*). - Call CheckObjectCoercible(
*baseValue*). - Let
*propertyNameString*be ToString(*propertyNameValue*). - If the syntactic production that is being evaluated is contained in
*strict*mode code, let*strict*be true, else let*strict*be**false**.

© Ecma International 2009**67**

8. Return a value of type Reference whose base value is *baseValue* and whose referenced name is

*propertyNameString*, and whose strict mode flag is *strict*.

The production

`new`

Operator`new`

- Let
*ref*be the result of evaluating*NewExpression*. - Let
*constructor*be GetValue(*ref*). - If Type(
*constructor*) is not Object, throw a TypeError exception. - If
*constructor*does not implement the [[Construct]] internal method, throw a TypeError exception. - Return the result of calling the [[Construct]] internal method on
*constructor*, providing no arguments (that is, an empty list of arguments).

`new`

- Let
*ref*be the result of evaluating*MemberExpression*. - Let
*constructor*be GetValue(*ref*). - Let
*argList*be the result of evaluating*Arguments*, producing an internal list of argument values (11.2.4). - If Type(
*constructor*) is not Object, throw a**TypeError**exception. - If
*constructor*does not implement the [[Construct]] internal method, throw a**TypeError**exception. - Return the result of calling the [[Construct]] internal method on
*constructor*, providing the list*argList*as the argument values.

- Let
*ref*be the result of evaluating*MemberExpression*. - Let
*func*be GetValue(*ref*). - Let
*argList*be the result of evaluating*Arguments*, producing an internal list of argument values (see 11.2.4). - If Type(
*func*) is not Object, throw a**TypeError**exception. - If IsCallable(
*func*) is**false**, throw a**TypeError**exception. - If Type(
*ref*) is Reference, then- If IsPropertyReference(
*ref*) is**true**, then- Let
*thisValue*be GetBase(*ref*).

- Let
- Else, the base of ref is an Environment Record
- Let
*thisValue*be the result of calling the ImplicitThisValue concrete method of GetBase(*ref*).

- Let

- If IsPropertyReference(
- Else, Type(
*ref*) is not Reference.- Let
*thisValue*be**undefined**.

- Let
- Return the result of calling the [[Call]] internal method on
*func*, providing*thisValue*as the**this**value and providing the list*argList*as the argument values.

NOTE The returned result will never be of type Reference if *func* is a native ECMAScript object. Whether calling a
host object can return a value of type Reference is implementation-dependent. If a value of type Reference is returned, it
must be a non-strict Property Reference.

The production

© Ecma International 2009**68**

- Return an empty List.

- Return the result of evaluating
*ArgumentList*.

- Let
*ref*be the result of evaluating*AssignmentExpression*. - Let
*arg*be GetValue(*ref*). - Return a List whose sole item is
*arg*.

`,`

- Let
*precedingArgs*be the result of evaluating*ArgumentList*. - Let
*ref*be the result of evaluating*AssignmentExpression*. - Let
*arg*be GetValue(*ref*). - Return a List whose length is one greater than the length of
*precedingArgs*and whose items are the items of*precedingArgs*, in order, followed at the end by*arg*which is the last item of the new list.

- Return the result of evaluating
*FunctionExpression.*

- PostfixExpression
**:** - LeftHandSideExpression

LeftHandSideExpression**[no**LineTerminator**here] ++**

LeftHandSideExpression**[no**LineTerminator**here]**- -

- Let
*lhs*be the result of evaluating*LeftHandSideExpression*. - Throw a
**SyntaxError**exception if the following conditions are all true:- Type(
*lhs*) is Reference is**true** - IsStrictReference(
*lhs*) is**true** - Type(GetBase(
*lhs*)) is Enviroment Record - GetReferencedName(
*lhs*) is either`"eval"`

or`"arguments"`

- Type(
- Let
*oldValue*be ToNumber(GetValue(*lhs*)). - Let
*newValue*be the result of adding the value`1`

to*oldValue*, using the same rules as for the`+`

operator (see 11.6.3). - Call PutValue(
*lhs*,*newValue*). - Return
*oldValue*.

- Let
*lhs*be the result of evaluating*LeftHandSideExpression*. - Throw a
**SyntaxError**exception if the following conditions are all true:- Type(
*lhs*) is Reference is**true**

- Type(

© Ecma International 2009**69**

- IsStrictReference(
*lhs*) is true - Type(GetBase(
*lhs*)) is Enviroment Record - GetReferencedName(
*lhs*) is either "eval" or "arguments"

- Let
*oldValue*be ToNumber(GetValue(*lhs*)). - Let
*newValue*be the result of subtracting the value`1`

from*oldValue*, using the same rules as for the - operator (11.6.3). - Call PutValue(
*lhs*,*newValue*). - Return
*oldValue*.

- UnaryExpression
**:** - PostfixExpression
`delete`

UnaryExpression`void`

UnaryExpression

`typeof`

UnaryExpression`++`

UnaryExpression`--`

UnaryExpression

`+`

UnaryExpression`-`

UnaryExpression`~`

UnaryExpression`!`

UnaryExpression

`delete`

Operator`delete`

- Let
*ref*be the result of evaluating UnaryExpression. - If Type(
*ref*) is not Reference, return**true**. - If IsUnresolvableReference(
*ref*) then,- If IsStrictReference(
*ref*) is**true**, throw a**SyntaxError**exception. - Else, return true.

- If IsStrictReference(
- If IsPropertyReference(
*ref*) is**true**, then- Return the result of calling the [[Delete]] internal method on ToObject(GetBase(
*ref*) providing GetReferencedName(*ref*) and IsStrictReference(*ref*) as the arguments. )

- Return the result of calling the [[Delete]] internal method on ToObject(GetBase(
- Else,
*ref*is a Reference to an Environment Record binding, so- If IsStrictReference(
*ref*) is**true**, throw a**SyntaxError**exception. - Let
*bindings*be GetBase(*ref*). - Return the result of calling the DeleteBinding concrete method of
*bindings*, providing GetReferencedName(*ref*) as the argument.

- If IsStrictReference(

NOTE When a **SyntaxError** exception is thrown if its
*UnaryExpression* is a direct reference to a variable, function argument, or function name. In addition, if a **false** }, a **TypeError**
exception is thrown.

`delete`

operator occurs within strict mode code, a `delete`

operator
occurs within strict mode code and the property to be deleted has the attribute { [[Configurable]]: `void`

Operator`void`

- Let
*expr*be the result of evaluating*UnaryExpression*. - Call GetValue(
*expr*). - Return
**undefined**.

NOTE GetValue must be called even though its value is not used because it may have observable side-effects.

© Ecma International 2009**70**

`typeof`

Operator`typeof`

- Let val be the result of evaluating UnaryExpression.
- If Type(
*val*) is Reference, then- If IsUnresolvableReference(
*val*) is**true**, return "`undefined`

". - Let
*val*be GetValue(*val*).

- If IsUnresolvableReference(
- Return a String determined by Type(
*val*) according to Table 20.

Type of val | Result |

Undefined | "`undefined` " |

Null | "`object` " |

Boolean | "`boolean` " |

Number | "`number` " |

String | "`string` " |

Object (native and does not implement [[Call]]) | "`object` " |

Object (native or host and does implement [[Call]]) | "`function` " |

Object (host and does not implement [[Call]]) | Implementation-defined except may
not be "`undefined` ", "`boolean` ",
"`number` ", or "`string` ". |

- Let
*expr*be the result of evaluating*UnaryExpression*. - Throw a
**SyntaxError**exception if the following conditions are all true:- Type(
*expr*) is Reference is**true** - IsStrictReference(
*expr*) is**true** - Type(GetBase(
*expr*)) is Enviroment Record - GetReferencedName(
*expr*) is either "`eval`

" or "`arguments`

"

- Type(
- Let oldValue be ToNumber(GetValue(
*expr*)). - Let newValue be the result of adding the value
`1`

to*oldValue*, using the same rules as for the`+`

operator (see 11.6.3). - Call PutValue(
*expr*,*newValue*). - Return .

- Let
*expr*be the result of evaluating*UnaryExpression*. - Throw a
**SyntaxError**exception if the following conditions are all true:- Type(
*expr*) is Reference is true - IsStrictReference(
*expr*) is true - Type(GetBase(
*expr*)) is Enviroment Record - GetReferencedName(
*expr*) is either "`eval`

" or "`arguments`

"

- Type(
- Let
*oldValue*be ToNumber(GetValue(*expr*)).

© Ecma International 2009**71**

- Let
*newValue*be the result of subtracting the value 1 from*oldValue*, using the same rules as for the - operator (see 11.6.3). - Call PutValue(
*expr*,*newValue*). - Return
*newValue*.

The production

- Let
*expr*be the result of evaluating*UnaryExpression*. - Return ToNumber(GetValue(
*expr*)).

The production

- Let
*expr*be the result of evaluating*UnaryExpression*. - Let oldValue be ToNumber(GetValue(
*expr*)). - If oldValue is
**NaN**, return**NaN**. - Return the result of negating oldValue; that is, compute a Number with the same magnitude but opposite sign.

- Let
*expr*be the result of evaluating*UnaryExpression*. - Let
*oldValue*be ToInt32(GetValue(*expr*)). - Return the result of applying bitwise complement to
*oldValue*. The result is a signed 32-bit integer.

- Let
*expr*be the result of evaluating*UnaryExpression*. - Let
*oldValue*be ToBoolean(GetValue(*expr*)). - If
*oldValue*is**true**, return**false**. - Return
**true**.

- MultiplicativeExpression
**:** - UnaryExpression

MultiplicativeExpression`*`

UnaryExpression

MultiplicativeExpression`/`

UnaryExpression

MultiplicativeExpression`%`

UnaryExpression

The production

© Ecma International 2009**72**

- Let left be the result of evaluating MultiplicativeExpression.
- Let leftValue be GetValue(left).
- Let right be the result of evaluating UnaryExpression.
- Let rightValue be GetValue(right).
- Let leftNum be ToNumber(leftValue).
- Let rightNum be ToNumber(rightValue).
- Return the result of applying the specified operation (*, /, or %) to leftNum and rightNum. See the Notes below 11.5.1, 11.5.2, 11.5.3.

- If either operand is NaN, the result is
**NaN**. - The sign of the result is positive if both operands have the same sign, negative if the operands have different signs.
- Multiplication of an infinity by a zero results in
**NaN**. - Multiplication of an infinity by an infinity results in an infinity. The sign is determined by the rule already stated above.
- Multiplication of an infinity by a finite non-zero value results in a signed infinity. The sign is determined by the rule already stated above.
- In the remaining cases, where neither an infinity or
**NaN**is involved, the product is computed and rounded to the nearest representable value using IEEE 754 round-to-nearest mode. If the magnitude is too large to represent, the result is then an infinity of appropriate sign. If the magnitude is too small to represent, the result is then a zero of appropriate sign. The ECMAScript language requires support of gradual underflow as defined by IEEE 754.

- If either operand is NaN, the result is
**NaN**. - The sign of the result is positive if both operands have the same sign, negative if the operands have different signs.
- Division of an infinity by an infinity results in
**NaN**. - Division of an infinity by a zero results in an infinity. The sign is determined by the rule already stated above.
- Division of an infinity by a non-zero finite value results in a signed infinity. The sign is determined by the rule already stated above.
- Division of a finite value by an infinity results in zero. The sign is determined by the rule already stated above.
- Division of a zero by a zero results in
**NaN**; division of zero by any other finite value results in zero, with the sign determined by the rule already stated above. - Division of a non-zero finite value by a zero results in a signed infinity. The sign is determined by the rule already stated above.
- In the remaining cases, where neither an infinity, nor a zero, nor
**NaN**is involved, the quotient is computed and rounded to the nearest representable value using IEEE 754 round to- nearest mode. If the magnitude is too large to represent, the operation overflows; the result is then an infinity of appropriate sign. If the magnitude is too small to represent, the

© Ecma International 2009**73**

operation underflows and the result is a zero of the appropriate sign. The ECMAScript
language requires support of gradual underflow as defined by IEEE 754.

NOTE 1 NOTE In C and C++, the remainder operator accepts only integral operands; in ECMAScript, it also accepts floating-point
operands.

The result of a floating-point remainder operation as computed by the % operator is not the same as the
"remainder" operation defined by IEEE 754. The IEEE 754 "remainder" operation computes the remainder
from a rounding division, not a truncating division, and so its behaviour is not analogous to that of the usual
integer remainder operator. Instead the ECMAScript language defines % on floating-point operations to
behave in a manner analogous to that of the Java integer remainder operator; this may be compared with the
C library function fmod.
The result of an ECMAScript floating-point remainder operation is determined by the rules of IEEE arithmetic:

- If either operand is
**NaN**, the result is**NaN**. - The sign of the result equals the sign of the dividend.
- If the dividend is an infinity, or the divisor is a zero, or both, the result is
**NaN**. - If the dividend is finite and the divisor is an infinity, the result equals the dividend.
- If the dividend is a zero and the divisor is finite, the result is the same as the dividend.
- In the remaining cases, where neither an infinity, nor a zero, nor
**NaN**is involved, the floating-point remainder r from a dividend n and a divisor d is defined by the mathematical relation r = n − (d × q) where q is an integer that is negative only if n/d is negative and positive only if n/d is positive, and whose magnitude is as large as possible without exceeding the magnitude of the true mathematical quotient of n and d.

- AdditiveExpression
**:** - MultiplicativeExpression

AdditiveExpression`+`

MultiplicativeExpression

AdditiveExpression`-`

MultiplicativeExpression

- Let
*lref*be the result of evaluating AdditiveExpression. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating MultiplicativeExpression. - Let
*rval*be GetValue(*rref*). - Let
*lprim*be ToPrimitive(*lval*). - Let
*rprim*be ToPrimitive(*rval*). - If Type(
*lprim*) is String or Type(*rprim*) is String, then- Return the String that is the result of concatenating ToString(
*lprim*) followed by ToString(*rprim*)

- Return the String that is the result of concatenating ToString(
- Return the result of applying the addition operation to ToNumber(
*lprim*) and ToNumber(*rprim*). See the Note below 11.6.3.

NOTE 1 No hint is provided in the calls to ToPrimitive in steps 5 and 6. All native ECMAScript objects except Date
objects handle the absence of a hint as if the hint Number were given; Date objects handle the absence of a hint as if the
hint String were given. Host objects may handle the absence of a hint in some other manner.

© Ecma International 2009**74**

NOTE 2 Step 7 differs from step 3 of the comparison algorithm for the relational operators (11.8.5), by using the
logical-or operation instead of the logical-and operation.

- Let
*lref*be the result of evaluating AdditiveExpression. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating MultiplicativeExpression. - Let
*rval*be GetValue(*rref*). - Let
*lnum*be ToNumber(*lval*). - Let
*rnum*be ToNumber(*rval*). - Return the result of applying the subtraction operation to
*lnum*and*rnum*. See the note below 11.6.3.

- If either operand is NaN, the result is
**NaN**. - The sum of two infinities of opposite sign is
**NaN**. - The sum of two infinities of the same sign is the infinity of that sign.
- The sum of an infinity and a finite value is equal to the infinite operand.
- The sum of two negative zeros is
**−0**. The sum of two positive zeros, or of two zeros of opposite sign, is**+0**. - The sum of a zero and a nonzero finite value is equal to the nonzero operand.
- The sum of two nonzero finite values of the same magnitude and opposite sign is
**+0**. - In the remaining cases, where neither an infinity, nor a zero, nor
**NaN**is involved, and the operands have the same sign or have different magnitudes, the sum is computed and rounded to the nearest representable value using IEEE 754 round-to-nearest mode. If the magnitude is too large to represent, the operation overflows and the result is then an infinity of appropriate sign. The ECMAScript language requires support of gradual underflow as defined by IEEE 754.

- ShiftExpression
**:** - AdditiveExpression

ShiftExpression`<<`

AdditiveExpression

ShiftExpression`>>`

AdditiveExpression

ShiftExpression`>>>`

AdditiveExpression

© Ecma International 2009**75**

The production *ShiftExpression*** : ***ShiftExpression* << *AdditiveExpression* is evaluated as follows:

### 11.7.2 The Signed Right Shift Operator ( >> )

Performs a sign-filling bitwise right shift operation on the left operand by the amount specified by the right
operand.

The production ShiftExpression** : **ShiftExpression >> AdditiveExpression is evaluated as follows:

### 11.7.3 The Unsigned Right Shift Operator ( >>> )

Performs a zero-filling bitwise right shift operation on the left operand by the amount specified by the right
operand.

The production ShiftExpression** : **ShiftExpression >>> AdditiveExpression is evaluated as follows:

- Let
*lref*be the result of evaluating ShiftExpression. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating AdditiveExpression. - Let
*rval*be GetValue(*rref*). - Let
*lnum*be ToInt32(*lval*). - Let
*rnum*be ToUint32(*rva*l). - Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute
*rnum*& 0x1F. - Return the result of left shifting lnum by shiftCount bits. The result is a signed 32-bit integer.

The production ShiftExpression

- Let
*lref*be the result of evaluating ShiftExpression. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating AdditiveExpression. - Let
*rval*be GetValue(*rref*). - Let
*lnum*be ToInt32(*lval*). - Let
*rnum*be ToUint32(*rval*). - Let shiftCount be the result of masking out all but the least significant 5 bits of
*rnum*, that is, compute*rnum*& 0x1F. - Return the result of performing a sign-extending right shift of
*lnum*by*shiftCount*bits. The most significant bit is propagated. The result is a signed 32-bit integer.

The production ShiftExpression

- Let
*lref*be the result of evaluating ShiftExpression. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating AdditiveExpression. - Let
*rval*be GetValue(*rref*). - Let
*lnum*be ToUint32(*lval*). - Let
*rnum*be ToUint32(*rval*). - Let shiftCount be the result of masking out all but the least significant 5 bits of
*rnum*, that is, compute*rnum*& 0x1F. - Return the result of performing a zero-filling right
*shift*of*lnum*by*shiftCount*bits. Vacated bits are filled with zero. The result is an unsigned 32-bit integer.

© Ecma International 2009**76**

- 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

NOTE The "NoIn" variants are needed to avoid confusing the

`in`

operator in a relational expression with the `in`

operator in a `for`

statement.The result of evaluating a relational operator is always of type Boolean, reflecting whether the relationship named by the operator holds between its two operands.

The

- Let
*lref*be the result of evaluating*RelationalExpression*. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating*ShiftExpression*. - Let
*rval*be GetValue(*rref*). - Let
*r*be the result of performing abstract relational comparison*lval*<*rval*. (see 11.8.5) - If
*r*is**undefined**, return**false**. Otherwise, return*r*.

- Let
*lref*be the result of evaluating*RelationalExpression*. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating*ShiftExpression*. - Let
*rval*be GetValue(*rref*). - Let
*r*be the result of performing abstract relational comparison rval <*lval*with*LeftFirst*equal to**false**. (see 11.8.5). - If
*r*is**undefined**, return**false**. Otherwise, return*r*.

© Ecma International 2009**77**

- 1. Let
*lref*be the result of evaluating*RelationalExpression*. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating*ShiftExpression*. - Let
*rval*be GetValue(*rref*). - Let
*r*be the result of performing abstract relational comparison*rval*<*lval*with*LeftFirst*equal to**false**. (see 11.8.5). - If r is true or undefined, return
**false**. Otherwise, return**true**.

- Let
*lref*be the result of evaluating*RelationalExpression*. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating*ShiftExpression*. - Let
*rval*be GetValue(*rref*). - Let
*r*be the result of performing abstract relational comparison*lval*<*rval*. (see 11.8.5) - If
*r*is true or undefined, return**false**. Otherwise, return**true**.

- If the
*LeftFirst*flag is**true**, then- Let
*px*be the result of calling ToPrimitive(*x*, hint Number). - Let
*py*be the result of calling ToPrimitive(*y*, hint Number).

- Let
- Else the order of evaluation needs to be reversed to preserve left to right evaluation
- Let
*py*be the result of calling ToPrimitive(*y*, hint Number). - Let
*px*be the result of calling ToPrimitive(*x*, hint Number).

- Let
- If it is not the case that both Type(
*px*) is String and Type(*py*) is String, then- Let
*nx*be the result of calling ToNumber(*px*). Because*px*and*py*are primitive values evaluation order is not important. - Let
*ny*be the result of calling ToNumber(*py*). - If
*nx*is**NaN**, return**undefined**. - If
*ny*is**NaN**, return**undefined**. - If
*nx*and ny are the same Number value, return**false**. - If
*nx*is +0 and*ny*is −0, return**false**. - If
*nx*is −0 and*ny*is +0, return**false**. - If
*nx*is +∞, return**false**. - If
*ny*is +∞, return**true**. - If
*ny*is −∞, return**false**. - If
*nx*is −∞, return**true**. - If the mathematical value of nx is less than the mathematical value of
*ny*—note that these mathematical values are both finite and not both zero—return**true**. Otherwise, return**false**.

- Let
- Else, both
*px*and*py*are Strings- If
*py*is a prefix of*px*, return**false**. (A String value*p*is a prefix of String value*q*if*q*can be the result of concatenating*p*and some other String*r*. Note that any String is a prefix of itself, because*r*may be the empty String.)

- If

© Ecma International 2009**78**

- If
*px*is a prefix of*py*, return true. - Let
*k*be the smallest nonnegative integer such that the character at position*k*within*px*is different from the character at position*k*within*py*. (There must be such a*k*, for neither String is a prefix of the other.) - Let
*m*be the integer that is the code unit value for the character at position*k*within*px*. - Let
*n*be the integer that is the code unit value for the character at position*k*within*py*. - If
*m*<*n*, return**true**. Otherwise, return**false**.

NOTE 1 Step 3 differs from step 7 in the algorithm for the addition operator + (11.6.1) in using and instead of or.

NOTE 2 The comparison of Strings uses a simple lexicographic ordering on sequences of code unit values. There is no
attempt to use the more complex, semantically oriented definitions of character or string equality and collating order
defined in the Unicode specification. Therefore String values that are canonically equal according to the Unicode standard
could test as unequal. In effect this algorithm assumes that both Strings are already in normalised form. Also, note that for
strings containing supplementary characters, lexicographic ordering on sequences of UTF-16 code unit values differs from
that on sequences of code point values.

`instanceof`

- Let
*lref*be the result of evaluating*RelationalExpression*. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating*ShiftExpression*. - Let
*rval*be GetValue(*rref*). - If Type(
*rval*) is not Object, throw a**TypeError**exception. - If
*rval*does not have a [[HasInstance]] internal method, throw a**TypeError**exception. - Return the result of calling the [[HasInstance]] internal method of
*rval*with argument*lval*.

The production

- Let
*lref*be the result of evaluating*RelationalExpression*. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating*ShiftExpression*. - Let
*rval*be GetValue(*rref*). - If Type(
*rval*) is not Object, throw a**TypeError**exception. - Return the result of calling the [[HasProperty]] internal method of
*rval*with argument ToString(*lval*).

- EqualityExpression
**:** - RelationalExpression
- EqualityExpression
**==**RelationalExpression - EqualityExpression
`!`

**=**RelationalExpression - EqualityExpression
**===**RelationalExpression - EqualityExpression
`!`

**==**RelationalExpression

- EqualityExpressionNoIn
**:** - RelationalExpressionNoIn
- EqualityExpressionNoIn
**==**RelationalExpressionNoIn - EqualityExpressionNoIn
`!`

**=**RelationalExpressionNoIn - EqualityExpressionNoIn
**===**RelationalExpressionNoIn - EqualityExpressionNoIn
`!`

**==**RelationalExpressionNoIn

© Ecma International 2009**79**

The result of evaluating an equality operator is always of type Boolean, reflecting whether the relationship named by the operator holds between its two operands.

The

- Let
*lref*be the result of evaluating*EqualityExpression*. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating*RelationalExpression*. - Let
*rval*be GetValue(*rref*). - Return the result of performing abstract equality comparison
*rval*==*lval*. (see 11.9.3).

- Let
*lref*be the result of evaluating*EqualityExpression*. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating*RelationalExpression*. - Let
*rval*be GetValue(*rref*). - Let
*r*be the result of performing abstract equality comparison*rval*==*lval*. (see 11.9.3). - If
*r*is**true**, return**false**. Otherwise, return**true**.

- If Type(
*x*) is the same as Type(y), then- If Type(
*x*) is Undefined, return**true**. - If Type(
*x*) is Null, return**true**. - If Type(
*x*) is Number, then- If
*x*is**NaN**, return**false**. - If
*y*is**NaN**, return**false**. - If
*x*is the same Number value as*y*, return**true**. - If
*x*is +**0**and*y*is −**0**, return**true**. - If
*x*is −**0**and*y*is +**0**, return**true**. - Return
**false**.

- If
- If Type(
*x*) is String, then return**true**if*x*and*y*are exactly the same sequence of characters (same length and same characters in corresponding positions). Otherwise, return**false**. - If Type(
*x*) is Boolean, return**true**if*x*and*y*are both**true**or both**false**. Otherwise, return**false**. - Return
**true**if*x*and*y*refer to the same object. Otherwise, return**false**.

- If Type(
- If
*x*is**null**and*y*is**undefined**, return**true**. - If
*x*is**undefined**and*y*is**null**, return**true**. - If Type(
*x*) is Number and Type(*y*) is String, return the result of the comparison*x*== ToNumber(*y*). - If Type(
*x*) is String and Type(*y*) is Number, return the result of the comparison ToNumber(*x*) ==*y*. - If Type(
*x*) is Boolean, return the result of the comparison ToNumber(*x*) ==*y*. - If Type(
*y*) is Boolean, return the result of the comparison*x*== ToNumber(*y*). - If Type(
*x*) is either String or Number and Type(*y*) is Object, return the result of the comparison*x*== ToPrimitive(*y*).

© Ecma International 2009**80**

9. If Type(*x*) is Object and Type(*y*) is either String or Number,

return the result of the comparison ToPrimitive(*x*) == *y*.

10. Return**false**.

return the result of the comparison ToPrimitive(

10. Return

NOTE 1 Given the above definition of equality:

- String comparison can be forced by:
`"" + a`

**==**`"" + b`

. - Numeric comparison can be forced by:
`+a`

**=**`+b`

. - Boolean comparison can be forced by:
`!a`

**=**`!b`

.

NOTE 2 The equality operators maintain the following invariants:

`A`

is equivalent to`!`

**=**B`!(A`

.**==**B)`A`

is equivalent to**==**B`B`

, except in the order of evaluation of**==**A`A`

and`B`

.

NOTE 3 The equality operator is not always transitive. For example, there might be two distinct String objects, each
representing the same String value; each String object would be considered equal to the String value by the == operator,
but the two String objects would not be equal to each other.

NOTE 4 Comparison of Strings uses a simple equality test on sequences of code unit values. There is no attempt to
use the more complex, semantically oriented definitions of character or string equality and collating order defined in the
Unicode specification. Therefore Strings values that are canonically equal according to the Unicode standard could test as
unequal. In effect this algorithm assumes that both Strings are already in normalized form.

- Let
*lref*be the result of evaluating*EqualityExpression*. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating.*RelationalExpression* - Let
*rval*be GetValue(*rref*). - Return the result of performing the strict equality comparison
*rval*===*lval*. (See 11.9.6)

- Let
*lref*be the result of evaluating*EqualityExpression*. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating*RelationalExpression*. - Let
*rval*be GetValue(*rref*). - Let
*r*be the result of performing strict equality comparison*rval*===*lval*. (See 11.9.6) - If
*r*is**true**, return**false**. Otherwise, return**true**.

- If Type(
*x*) is different from Type(*y*), return**false**. - If Type(
*x*) is Undefined, return**true**. - If Type(
*x*) is**Null**, return**true**. - If Type(x) is Number, then
- If
*x*is**NaN**, return false. - If
*y*is**NaN**, return false. - If
*x*is the same Number value as*y*, return**true**. - If
*x*is +**0**and*y*is −**0**, return**true**. - If
*x*is −**0**and*y*is +**0**, return**true**. - Return false.

- If

© Ecma International 2009**81**

- If Type(
*x*) is String, then return**true**if*x*and*y*are exactly the same sequence of characters (same length and

same characters in corresponding positions); otherwise, return**false**. - If Type(
*x*) is Boolean, return**true**if*x*and*y*are both**true**or both**false**; otherwise, return**false**. - Return
**true**if*x*and*y*refer to the same object. Otherwise, return**false**.

NOTE This algorithm differs from the SameValue Algorithm (9.12) in its treatment of signed zeroes and NaNs.

- BitwiseANDExpression
**:** - EqualityExpression

BitwiseANDExpression`&`

EqualityExpression

- BitwiseANDExpressionNoIn
**:** - EqualityExpressionNoIn

BitwiseANDExpressionNoIn`&`

EqualityExpressionNoIn

- BitwiseXORExpression
**:** - BitwiseANDExpression

BitwiseXORExpression`^`

BitwiseANDExpression

- BitwiseXORExpressionNoIn
**:** - BitwiseANDExpressionNoIn

BitwiseXORExpressionNoIn`^`

BitwiseANDExpressionNoIn

- BitwiseORExpression
**:** - BitwiseXORExpression

BitwiseORExpression`|`

BitwiseXORExpression

- BitwiseORExpressionNoIn
**:** - BitwiseXORExpressionNoIn

BitwiseORExpressionNoIn`|`

BitwiseXORExpressionNoIn

The production

- Let
*lref*be the result of evaluating A. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating B. - Let
*rval*be GetValue(*rref*). - Let
*lnum*be ToInt32(*lval*). - Let
*rnum*be ToInt32(*rval*). - Return the result of applying the bitwise operator @ to
*lnum*and*rnum*. The result is a signed 32 bit integer.

- LogicalANDExpression
**:** - BitwiseORExpression

LogicalANDExpression`&&`

BitwiseORExpression

- LogicalANDExpressionNoIn
**:** - BitwiseORExpressionNoIn

LogicalANDExpressionNoIn`&&`

BitwiseORExpressionNoIn

© Ecma International 2009**82**

- LogicalORExpression
**:** - LogicalANDExpression

LogicalORExpression | | LogicalANDExpression

- LogicalORExpressionNoIn
**:** - LogicalANDExpressionNoIn

LogicalORExpressionNoIn | | LogicalANDExpressionNoIn

The production

- Let
*lref*be the result of evaluating*LogicalANDExpression*. - Let
*lval be GetValue(*).*lref* - If ToBoolean(
*lval*) is**false**, return*lval*. - Let
*rref*be the result of evaluating*BitwiseORExpression*. - Return GetValue(
*rref*).

- Let
*lref*be the result of evaluating*LogicalORExpression*. - Let
*lval*be GetValue(*lref*). - If ToBoolean(
*lval*) is**true**, return*lval*. - Let
*rref*be the result of evaluating*LogicalANDExpression*. - Return GetValue(
*rref*).

NOTE The value produced by a

`&&`

or `||`

operator is not necessarily of type Boolean. The value produced will always
be the value of one of the two operand expressions.- ConditionalExpression
**:** - LogicalORExpression

LogicalORExpression`?`

AssignmentExpression`:`

AssignmentExpression

- ConditionalExpressionNoIn
**:** - LogicalORExpressionNoIn

LogicalORExpressionNoIn`?`

AssignmentExpressionNoIn`:`

AssignmentExpressionNoIn

The production

- Let
*lref*be the result of evaluating*LogicalORExpression*. - If ToBoolean(GetValue(
*lref*)) is**true**, then- Let
*trueRef*be the result of evaluating the first*AssignmentExpression*. - Return GetValue(
*trueRef*).

- Let
- Else
- Let
*falseRef*be the result of evaluating the second*AssignmentExpression*. - Return GetValue(
*falseRef*).

- Let

© Ecma International 2009**83**

The *ConditionalExpressionNoIn* production is evaluated in the same manner as the *ConditionalExpression*
production except that the contained *LogicalORExpressionNoIn*, *AssignmentExpression* and
*AssignmentExpressionNoIn* are evaluated instead of the contained *LogicalORExpression*, first
*AssignmentExpression* and second *AssignmentExpression*, respectively.

### 11.13 Assignment Operators

**Syntax**
**Semantics**

The*AssignmentExpressionNoIn* productions are evaluated in the same manner as the *AssignmentExpression*
productions except that the contained *ConditionalExpressionNoIn* and *AssignmentExpressionNoIn* are evaluated
instead of the contained *ConditionalExpression* and *AssignmentExpression*, respectively.
### 11.13.1 Simple Assignment ( = )

The production *AssignmentExpression* : *LeftHandSideExpression* = *AssignmentExpression* is evaluated as follows:
### 11.13.2 Compound Assignment ( op= )

The production *AssignmentExpression* : *LeftHandSideExpression* @ = *AssignmentExpression*, where @ represents
one of the operators indicated above, is evaluated as follows:

NOTE The grammar for a ConditionalExpression in ECMAScript is a little bit different from that in C and Java, which
each allow the second subexpression to be an Expression but restrict the third expression to be a ConditionalExpression.
The motivation for this difference in ECMAScript is to allow an assignment expression to be governed by either arm of a
conditional and to eliminate the confusing and fairly useless case of a comma expression as the centre expression.

- AssignmentExpression
**:** - ConditionalExpression

LeftHandSideExpression AssignmentOperator AssignmentExpression

- AssignmentExpressionNoIn
**:** - ConditionalExpressionNoIn

LeftHandSideExpression AssignmentOperator AssignmentExpressionNoIn

- AssignmentOperator
**one of** `= *= /= %= += -= <<= >>= >>>= &= ^= |=`

The

- Let
*lref*be the result of evaluating*LeftHandSideExpression*. - Let
*rref*be the result of evaluating*AssignmentExpression*. - Let
*rval*be GetValue(*rref*). - Throw a
**SyntaxError**exception if the following conditions are all true:- Type(
*lref*) is Reference is**true** - IsStrictReference(
*lref*) is**true** - Type(GetBase(
*lref*)) is Enviroment Record - GetReferencedName(
*lref*) is either`"eval"`

or`"arguments"`

- Type(
- Call PutValue(
*lref*,*rval*). - Return
*rval*.

NOTE When an assignment occurs within strict mode code, its *LeftHandSide* must not evaluate to an unresolvable
reference. If it does a **ReferenceError** exception is thrown upon assignment. The *LeftHandSide* also may not be a
reference to a data property with the attribute value {[[Writable]]:**false**}, to an accessor property with the attribute value
{[[Set]]:**undefined**}, nor to a non-existent property of an object whose [[Extensible]] internal property has the value **false**. In
these cases a **TypeError** exception is thrown.

© Ecma International 2009**84**

- Let
*lref*be the result of evaluating*LeftHandSideExpression*. - Let
*lval*be GetValue(*lref*). - Let
*rref*be the result of evaluating*AssignmentExpression*. - Let
*rval*be GetValue(*rref*). - Let
*r*be the result of applying operator @ to*lval*and*rval*. - Throw a
**SyntaxError**exception if the following conditions are all true:- Type(
*lref*) is Reference is**true** - IsStrictReference(
*lref*) is**true** - Type(GetBase(
*lref*)) is Enviroment Record - GetReferencedName(
*lref*) is either`"eval"`

or`"arguments"`

- Type(
- Call PutValue(
*lref*,*r*). - Return
*r*.

NOTE See NOTE 11.13.1.

`,`

)- Expression
**:** - AssignmentExpression

Expression`,`

AssignmentExpression

- ExpressionNoIn
**:** - AssignmentExpressionNoIn

ExpressionNoIn`,`

AssignmentExpressionNoIn

The production

`,`

- Let
*lref*be the result of evaluating*Expression*. - Call GetValue(
*lref*). - Let
*rref*be the result of evaluating*AssignmentExpression*. - Return GetValue(
*rref*).

NOTE GetValue must be called even though its value is not used because it may have observable side-effects.

© Ecma International 2009**85**