[Previous] [Next] [First] [Last]
This chapter specifies the meaning of JavaScript expressions and the rules for their evaluation.
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.
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.
i = 2 j = (i=3) * i println(j)
a = 9 a += (a =3) // first example println(a) b = 9 b = b + (b = 3) // second example println(b)
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.
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
A literal denotes a fixed, unchanging value.
The following production from Chapter 2 is repeated here for convenience:
Literal: IntegerLiteral FloatingPointLiteral BooleanLiteral StringLiteral NullLiteral
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.
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
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.
This section describe the processing of a function call.
At run time, a function call requires the following steps:
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.
The argument expressions are evaluated in order, from left to right.
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.
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
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.
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.
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.
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.
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.
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.
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.
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.
The delete operator removes a property definition, frees the memory associated with it, and results in undefined.2
The typeof operator returns a string specifying the type of its unevaluated operand. The operand is any expression. Syntax:
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"
The void operator takes a unary expression of any type as its operand, evaluates it, and results in undefined.
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.
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:
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:
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:
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.
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.
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.
"The square root of 2 is " + Math.sqrt(2)
"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".
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).
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.
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.
If both operands of a relational operator are string-convertible, they are converted to string and compared lexicographically.
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:
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.
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.
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.
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:
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 )
b1 = true b2 = false b3 = true b4 = true
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.
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.
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.
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.
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.
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.
A compound assignment expression of the form E1
op= E2 is equivalent to
E1 = (E1) op (E2), except that E1 is evaluated only once.
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.
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.