[Previous] [Next] [First] [Last]


Expressions

This chapter specifies the meaning of JavaScript expressions and the rules for their evaluation.

4.1 Evaluation, Denotation and Result

When a JavaScript expression is evaluated (executed), the result denotes one of three things:

Evaluation of an expression can also produce side effects, because expressions may contain embedded assignments, increment or decrement operators, and function calls.

An expression is void if it gets its value from a function call that does not return a value, or from use of the void operator.

If an expression denotes a variable, and a value is required for use in further evaluation, then the value of that variable is used. In this context, when the expression denotes a variable or a value, we may speak simply of the value of the expression.

4.2 Evaluation Order

In JavaScript, the operands to operators are evaluated from left to right.

The left operand of a binary operator is fully evaluated before any part of the right operand is evaluated. For example, if the left operand contains an assignment to a variable and the right operand contains a reference to that same variable, then the value produced by the reference will reflect the fact that the assignment occurred first.

Thus:

i = 2
j = (i=3) * i
println(j)

prints

9

And:

a = 9
a += (a =3) // first example
println(a)
b = 9
b = b + (b = 3) // second example
println(b)

prints

12
12

Every operand of an operator (except for &&, ||, and ? :) is fully evaluated before any part of the operation itself is performed.

In a function or constructor call, one or more argument expressions may appear within the parentheses, separated by commas. Each argument expression is fully evaluated before any part of any argument expression to its right is evaluated.

4.3 Primary Expressions

Primary expressions include most of the simplest kinds of expressions, from which all others are constructed: literals, function calls, and array accesses.

PrimaryExpr:
          Literal
          this

4.3.1 Literals

A literal denotes a fixed, unchanging value.

The following production from Chapter 2 is repeated here for convenience:

Literal:
          IntegerLiteral
          FloatingPointLiteral
          BooleanLiteral
          StringLiteral
          NullLiteral

4.3.2 this

The keyword this denotes a reference to the invoking object, or to the object being constructed in a constructor function. The invoking object is defined as the object name to the left of the period "." or left bracket "[" in a method call, otherwise it is the parent object of the function.

4.4 Member Expressions

A member expression is either a primary expression, a function call, or a named or indexed property expression.

MemberExpr:
          PrimaryExpr
          MemberExpr . Identifier
          MemberExpr [ Expression ]
          MemberExpr ( ArgumentListopt )

The definition of ArgumentList is repeated here for convenience:

ArgumentList:
          AssignmentExpression
          ArgumentList , AssignmentExpression

4.4.1 Property Expression Evaluation

A property expression combines a member expression and a property name. A property name is either an identifier to the right of the dot operator, or the string conversion of an expression enclosed by brackets.

The dot operator (.) joins an object reference to its left with an identifier to its right that names a property. If the left operand is not of object type, it is converted to object. The right operand must be an identifier or a compile-time error results. A property expression using the dot operator is called a dot expression.

The index operator ([ ]) joins an object reference to the left of the [ separator to an expression after the [ and before the ] separator. If the left operand is not of object type, it is converted to object. The right operand is converted to string, according to the conversion rules described in 3.1.2 Type Conversion.1 A property expression using the index operator is called an index expression.

4.4.2 Function Call Evaluation

This section describe the processing of a function call.

At run time, a function call requires the following steps:

4.4.2.1 Compute Target Reference

The member expression to the left of the argument list is evaluated and its result is converted to a function. If the conversion fails, then the program terminates. Otherwise, the function reference is the target to call.

4.4.2.2 Evaluate Arguments

The argument expressions are evaluated in order, from left to right.

4.4.2.3 Locate Function to Call

The body of the target function identified in the first step is executed, with the values of the arguments determined in the second step.

The arguments in the function call expression are paired with the corresponding formal arguments in the function definition. If there are fewer arguments than in the function definition, then the remaining formal arguments are undefined during the current call. If there are more arguments in the call expression than in the definition, these arguments are assigned to elements of the function's arguments array.

4.5 Unary Expressions

The unary operators include +, -, ++, --, ~, !, new, typeof, and void. Expressions with unary operators group right-to-left, so that -~x means the same as -(~x).

UnaryExpression:
          MemberExpression
          ! UnaryExpression
          ~ UnaryExpression
          - UnaryExpression
          ++ MemberExpression
          -- MemberExpression
          MemberExpression ++
          MemberExpression --
          new Constructor
          delete MemberExpression
          typeof UnaryExpression
          void UnaryExpression

4.5.1 Logical Complement Operator !

The operand of the ! operator must be convertible to a boolean value or a run-time error occurs. The type of the result is boolean and its value is true if the operand converts to false and false if the operand converts to true.

4.5.2 Bitwise Complement Operator ~

The operand of the unary ~ operator must be a convertible to a number or a run-time error occurs. The type of the result is number, and its value is the bitwise complement of the 32-bit integer converted value of the operand.

4.5.3 Unary Minus Operator -

The operand of the unary - operator must be convertible to a number or a run-time error occurs. The type of the result is number, and its value is the arithmetic negation of the converted value of the operand.

Special cases are:

4.5.4 Prefix Increment Operator ++

A member expression preceded by a ++ operator is a prefix increment expression. The result of the member expression must be a variable, or a run-time error occurs. The result of the prefix increment expression is not a variable, but a value.

At run time, the variable's value must be convertible to a number or an error occurs. The value 1 is added to the converted value of the variable and the sum is stored back into the variable. The value of the prefix increment expression is the value of the variable after the sum is stored.

4.5.5 Prefix Decrement Operator --

A member expression preceded by a -- operator is a prefix decrement expression. The result of the member expression must be a variable, or a run-time error occurs. The result of the prefix decrement expression is not a variable, but a value.

At run time, the variable's value must be convertible to a number or an error occurs. The value 1 is subtracted from the converted value of the variable and the difference is stored back into the variable. The value of the prefix decrement expression is the value of the variable after the difference is stored.

4.5.6 Postfix Increment Operator ++

A member expression followed by a ++ operator is a postfix increment expression. The result of the member expression must be a variable, or a run-time error occurs. The result of the postfix increment expression is not a variable, but a value.

At run time, the variable's value must be convertible to a number or an error occurs. The value 1 is added to the converted value of the variable and the sum is stored back into the variable. The value of the postfix increment expression is the value of the variable before the sum is stored.

4.5.7 Postfix Decrement Operator --

A member expression followed by a -- operator is a postfix decrement expression. The result of the member expression must be a variable, or a run-time error occurs. The result of the postfix decrement expression is not a variable, but a value.

At run time, the variable's value must be convertible to a number or an error occurs. The value 1 is subtracted from the converted value of the variable and the difference is stored back into the variable. The value of the postfix decrement expression is the value of the variable before the difference is stored.

4.5.8 The new operator

The new operator returns an object created with a constructor. The constructor is a function reference or function call expression where the function is named as in 3.5 Names. In addition to qualified names, this followed by a dot followed by a name can be used. The type of the result is object, and its value is a reference to the constructed object.

Constructor:
          this . ConstructorCall
          ConstructorCall

ConstructorCall:
          Identifier
          Identifier ( ArgumentListopt )
          Identifier . ConstructorCall

For more information on constructor functions, see 5.3 Constructor Functions.

4.5.9 The delete operator

The delete operator removes a property definition, frees the memory associated with it, and results in undefined.2

4.5.10 The typeof operator

The typeof operator returns a string specifying the type of its unevaluated operand. The operand is any expression. Syntax:

The string returned is one of

For example,

typeof foo returns "undefined"          // where foo is undefined
typeof eval returns "function"
typeof null returns "object"
typeof 3.14 returns "number"
typeof true returns "boolean"
typeof "abcdef" returns "string"

4.5.11 The void operator

The void operator takes a unary expression of any type as its operand, evaluates it, and results in undefined.

4.6 Multiplicative Operators

The operators *, /, and % are called the multiplicative operators. They have the same precedence and are syntactically left-associative (they group left-to-right).

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

The type of each of the operands of a multiplicative operator must be number or a run-time error occurs.

4.6.1 Multiplication Operator *

The binary * operator performs multiplication, producing the product of its operands. Multiplication is commutative. Multiplication is not always associative in JavaScript, because of finite precision.

The result of a floating-point multiplication is governed by the rules of IEEE 754 double-precision arithmetic:

4.6.2 Division Operator /

The binary / operator performs division, producing the quotient of its operands. The left operand is the dividend and the right operand is the divisor.

JavaScript does not perform integer division. The operands and result of all division operations are double-precision floating-point numbers. The result of division is determined by the specification of IEEE 754 arithmetic:

4.6.3 Remainder Operator %

The binary % operator is said to yield the remainder of its operands from an implied division; the left operand is the dividend and the right operand is the divisor. In C and C++, the remainder operator accepts only integral operands, but in JavaScript, 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 so-called "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 behavior is not analogous to that of the usual integer remainder operator. Instead the JavaScript 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 a JavaScript floating-point remainder operation is determined by the rules of IEEE arithmetic:

Examples

5%3 produces 2

5%(-3) produces 2

(-5)%3 produces -2

(-5)%(-3) produces -2

5.2345%3.0 produces 2.2345

5.0%(-3.0) produces 2.0

(-5.0)%3.0 produces -2.0

(-5.0)%(-3.0) produces -2.0

4.7 Additive Operators

The operators + and - are called the additive operators. They have the same precedence and are syntactically left-associative (they group left-to-right).

AdditiveExpression:
          MultiplicativeExpression
          AdditiveExpression + MultiplicativeExpression
          AdditiveExpression - MultiplicativeExpression

In an AdditiveExpression using the + operator, if either of the operands is of type string, object, or function, then the other operand is converted to a string and the operation is a string concatenation operation (see 4.7.1 String Concatenation Operator +). In the case of an object operand, this conversion occurs only if the object has no valueOf method or its valueOf method returns a string.4 Such an operand is called string-convertible.

If neither operand is string-convertible, the additive operators convert their operands to number, and result in a number.

4.7.1 String Concatenation Operator +

If only one operand expression is string-convertible, then string conversion is performed on the other operand to produce a string at run time. The result is a reference to a newly created string that is the concatenation of the two strings. The characters taken from the left operand precede the characters taken from the right operand in the newly created string.

4.7.1.1 String Conversion

Any object may be converted to type string by a call to the valueOf method, provided it returns a string. If it does not, and the object has a toString method, the toString method is called. For more information, see 3.1.2 Type Conversion.

4.7.1.2 Examples of String Concatenation

The example expression:

"The square root of 2 is " + Math.sqrt(2)

produces the result:

"The square root of 2 is 1.4142135623730952"

The + operator is syntactically left-associative, no matter whether it is later determined by type analysis to represent string concatenation or addition. In some cases care is required to get the desired result. For example, the expression: a + b + c is always regarded as meaning (a + b) + c. Therefore the result of the expression: 1 + 2 + " fiddlers" is
"3 fiddlers" but the result of "fiddlers " + 1 + 2 is "fiddlers 12".

4.7.2 Additive Operators (+ and -) for Numeric Types

The binary + operator performs addition when applied to two operands of numeric type, producing the sum of the operands. The binary - operator performs subtraction, producing the difference of two numeric operands.

Addition is a commutative operation, but not always associative.

The result of an addition is determined using the rules of IEEE 754 double-precision arithmetic:

The binary - operator performs subtraction when applied to two operands of numeric type producing the difference of its operands; the left operand is the minuend and the right operand is the subtrahend. It is always the case that a-b produces the same result as a+(-b).

4.8 Shift Operators

The shift operators include the left shift <<, the signed right shift >>, and the unsigned right shift >>>; they are syntactically left-associative (they group left-to- right). The left operand of a shift operator is the value to be shifted; the right operand specifies the number of bits to shift.

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

The type of each of the operands of a shift operator must be convertible to number or a run-time error occurs. At run time, shift operations are performed on the 32-bit two's complement integer representation of the value of the left operand. The right operand is converted to an integer, and only the least five bits are used (this is known as implicit masking).

The value of n<<s is n left-shifted s bit positions; this is equivalent (only if overflow does not occur) to multiplication by two to the power s.

The value of n>>s is n right-shifted s bit positions with sign-extension. For non-negative values of n, this is equivalent to truncating integer division by two to the power s.

The value of n>>>s is n right-shifted s bit positions with zero-extension. If n is positive, the result is the same as that of n>>s; if n is negative, the result is equal to that of the expression (n>>s)+(2<<~s). The added term (2<<~s) cancels out the propagated sign bit. Note that, because of the implicit masking of the right operand of a shift operator, ~s as a shift distance is equivalent to 31-s when shifting an int value and to 63-s when shifting a long value.

4.9 Relational Operators

The relational operators are syntactically left-associative (they group left-to- right), for example, a<b<c parses as (a<b)<c. If both operands are string-convertible (see 4.7 Additive Operators), both are converted to string, and the results are compared as strings. Otherwise, both operands must convert to number, or a run-time error occurs.

RelationalExpression:
          ShiftExpression
          RelationalExpression < ShiftExpression
          RelationalExpression > ShiftExpression
          RelationalExpression <= ShiftExpression
          RelationalExpression >= ShiftExpression

The type of a relational expression is always boolean.

4.9.1 String Comparison Operators

If both operands of a relational operator are string-convertible, they are converted to string and compared lexicographically.

4.9.2 Numerical Comparison Operators

If either operand of a relational operator is not string-convertible, then both must be convertible to number, or a run-time error occurs.

The result of a numerical comparison, as determined by the specification of the IEEE 754 standard, is:

Subject to these considerations, the following rules then hold for operands other than NaN:

4.10 Equality Operators

The equality operators are syntactically left-associative (they group left-to-right), for example, a==b==c parses as (a==b)==c. The result type of a==b is always boolean, and the value of c is therefore converted to boolean before it is compared. For example, if c is a number, then if it is zero, it has a boolean value of false; otherwise it is true. Thus a==b==c does not test to see whether a, b, and c are all equal.

EqualityExpression:
          RelationalExpression
          EqualityExpression == RelationalExpression
          EqualityExpression != RelationalExpression

The == (equal to) and the != (not equal to) operators are analogous to the relational operators except for their lower precedence. Thus, a<b==c<d is true whenever a<b and c<d have the same truth-value.The type of an equality expression is always boolean.

In all cases, a!=b produces the same result as !(a==b). The equality operators are commutative.

4.10.1 Reference Equality Operators == and !=

If both operands are of type object or function, they are compared as pointers. Otherwise, if either operand is null, the other is converted to object and compared with null.

4.10.2 String Equality Operators == and !=

If both operands are string-convertible, but both are not object or function, and neither is null, then they are compared byte-by-byte for equality or inequality.

4.10.3 Numerical Equality Operators == and !=

If neither operand is object, function, or string-convertible, then both are converted to number, and equality testing is performed in accordance with the rules of the IEEE 754 standard:

Subject to these considerations, the following rules then hold for operands other than NaN:

For example,

x = 345
y = 345
z = 1
b1 = 2 == 2 == 1
b2 = 2 == 3 == 1
b3 = 2 == 3 == 0
b4 = 2 == 3 == false
println("b1 = " + b1)
println("b2 = " + b2 )
println("b3 = " + b3 )
println("b4 = " + b4 )

The output of this script is

b1 = true
b2 = false
b3 = true
b4 = true

4.11 Bitwise Logical Operators

The bitwise logical operators include the AND operator &, exclusive OR operator ^, and inclusive OR operator |. These operators have different precedence, with & having the highest precedence and | the lowest precedence. Each operator is syntactically left-associative (each groups left-to-right). Each operator is both commutative and associative.

AndExpression:
          EqualityExpression
          AndExpression & EqualityExpression

ExclusiveOrExpression:
          AndExpression
          ExclusiveOrExpression ^ AndExpression

InclusiveOrExpression:
          ExclusiveOrExpression
          InclusiveOrExpression | ExclusiveOrExpression

The bitwise logical operators convert their operands to number, which may result in a run-time error. If both operands convert to number, the results are converted to 32-bit integers, and the result is also an integral number.

For &, the result value is the bitwise AND of the operand values. For ^, the result value is the bitwise exclusive OR of the operand values. For |, the result value is the bitwise inclusive OR of the operand values.

For example, the result of the expression 0xff00 & 0xf0f0 is 0xf000. The result of 0xff00 ^ 0xf0f0 is 0x0ff0.The result of 0xff00 | 0xf0f0 is 0xfff0.

4.12 Conditional-And Operator

The && operator is like & but evaluates its right operand only if the value of its left operand converts to true. It is syntactically left-associative (it groups left-to-right). It is fully associative with respect to both side effects and result value; that is, for any expressions a, b, and c, evaluation of the expression
( a && b ) && c produces the same result, with the same side effects occurring in the same order, as evaluation of the expression a && ( b && c ).

ConditionalAndExpression:
          InclusiveOrExpression
          ConditionalAndExpression && InclusiveOrExpression

Each operand of && must be convertible to type boolean or a run-time error occurs. The result type and value are the type and value of the left operand if it converts to false, otherwise the result type and value are those of the right operand.

At run time, the left operand is evaluated first; if its value converts to false, the right operand expression is not evaluated. If the value of the left operand converts to true, then the right expression is evaluated.

4.13 Conditional-Or Operator

The || operator is like | but evaluates its right operand only if the value of its left operand is false. It is syntactically left-associative (it groups left-to-right). It is fully associative with respect to both side effects and result value; that is, for any expressions a, b, and c, evaluation of the expression
( a || b ) || c produces the same result, with the same side effects occurring in the same order, as evaluation of the expression a || ( b || c).

ConditionalOrExpression:
          ConditionalAndExpression
          ConditionalOrExpression || ConditionalAndExpression

Each operand of || must be convertible to type boolean or a run-time error occurs. The result type and value are the type and value of the left operand if it converts to true, otherwise the result type and value are those of the right operand.

At run time, the left operand is evaluated first; if its value converts to true, the right operand expression is not evaluated. If the value of the left operand converts to false, then the right expression is evaluated.

4.14 Conditional Operator ? :

The conditional operator ? : uses the boolean value of one expression to decide which of two other expressions should be evaluated.

The conditional operator is syntactically right-associative (it groups right-to-left), so that a?b:c?d:e?f:g means the same as a?b:(c?d:(e?f:g)).

ConditionalExpression:
          ConditionalOrExpression
          ConditionalOrExpression ? AssignmentExpression : AssignmentExpression

The conditional operator has three operand expressions; ? appears between the first and second expressions, and : appears between the second and third expressions.

The first expression must convert to boolean or a run-time error occurs.

At run time, the first operand of the conditional expression is evaluated first and converted to boolean; the result is then used to choose either the second or the third operand expression:

The chosen operand is then evaluated and the resulting value is the result of the conditional expression. The operand not chosen is not evaluated for that particular evaluation of the conditional expression.

4.15 Assignment Operators

There are twelve assignment operators; all are syntactically right-associative (they group right-to-left). Thus a=b=c means a=(b=c), which assigns the value of c to b and then assigns the value of b to a.

AssignmentExpression:
          ConditionalExpression
          Assignment

Assignment:
          LeftHandSide AssignmentOperator AssignmentExpression

LeftHandSide:
          Identifier
          PropertyExpression

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

The result of the first operand of an assignment operator must be a variable or a compile-time error occurs.5

At run time, the type and value of the result are those of the variable after the assignment has occurred. The result of an assignment expression is not itself a variable.

4.15.1 Simple Assignment Operator =

At run time, the left operand is evaluated first, resulting in a variable. Next the right operand is evaluated and the result is stored into the variable.

4.15.2 Compound Assignment Operators

A compound assignment expression of the form E1 op= E2 is equivalent to
E1 = (E1) op (E2), except that E1 is evaluated only once.

4.16 Comma Operator

The comma operator has the lowest precedence of all JavaScript operators. Comma expressions may not occur in function argument lists, but may occur anywhere else an expression may occur, including between brackets in an index expression.

Expression:
          AssigmentExpression
          Expression , AssignmentExpression

The comma operator evaluates its left operand and then its right operand. Its result is the result of evaluating its right operand.


Footnotes

1 Implementations can optimize index expressions where the index is a nonnegative integer to associate the integer, not its string conversion, with the property value. Such implementations must treat a string index containing a nonnegative integer literal as equivalent to the integer index. JavaScript 1.1 as implemented in Navigator 3.0 fails to equate integer strings with integer indexes.

2 In JavaScript 1.1, as implemented in Navigator 3.0, delete does not remove the property definition, instead it sets the property to null.

3 In JavaScript 1.1, as implemented in Navigator 3.0, division of a non-zero finite value by zero results in NaN.

4 In JavaScript 1.1, as implemented in Navigator 3.0, the conversion from object to string occurs regardless of the existence or result type of the valueOf method.

5 In JavaScript 1.1, as implemented in Navigator 3.0, the check for a variable on the left side of an assignment operator is done at run time.


[Previous] [Next] [First] [Last]