7.1 Type Conversion

The ECMAScript language implicitly performs automatic type conversion as needed. To clarify the semantics of certain constructs it is useful to define a set of conversion abstract operations. The conversion abstract operations are polymorphic; they can accept a value of any ECMAScript language type. But no other specification types are used with these operations.

The BigInt type has no implicit conversions in the ECMAScript language; programmers must call BigInt explicitly to convert values from other types.

7.1.1 ToPrimitive ( input [ , preferredType ] )

The abstract operation ToPrimitive takes argument input and optional argument preferredType. It converts its input argument to a non-Object type. If an object is capable of converting to more than one primitive type, it may use the optional hint preferredType to favour that type. It performs the following steps when called:

  1. Assert: input is an ECMAScript language value.
  2. If Type(input) is Object, then
    1. Let exoticToPrim be ? GetMethod(input, @@toPrimitive).
    2. If exoticToPrim is not undefined, then
      1. If preferredType is not present, let hint be "default".
      2. Else if preferredType is string, let hint be "string".
      3. Else,
        1. Assert: preferredType is number.
        2. Let hint be "number".
      4. Let result be ? Call(exoticToPrim, input, « hint »).
      5. If Type(result) is not Object, return result.
      6. Throw a TypeError exception.
    3. If preferredType is not present, let preferredType be number.
    4. Return ? OrdinaryToPrimitive(input, preferredType).
  3. Return input.
Note

When ToPrimitive is called with no hint, then it generally behaves as if the hint were number. However, objects may over-ride this behaviour by defining a @@toPrimitive method. Of the objects defined in this specification only Date objects (see 21.4.4.45) and Symbol objects (see 20.4.3.5) over-ride the default ToPrimitive behaviour. Date objects treat no hint as if the hint were string.

7.1.1.1 OrdinaryToPrimitive ( O, hint )

The abstract operation OrdinaryToPrimitive takes arguments O and hint. It performs the following steps when called:

  1. Assert: Type(O) is Object.
  2. Assert: hint is either string or number.
  3. If hint is string, then
    1. Let methodNames be « "toString", "valueOf" ».
  4. Else,
    1. Let methodNames be « "valueOf", "toString" ».
  5. For each element name of methodNames, do
    1. Let method be ? Get(O, name).
    2. If IsCallable(method) is true, then
      1. Let result be ? Call(method, O).
      2. If Type(result) is not Object, return result.
  6. Throw a TypeError exception.

7.1.2 ToBoolean ( argument )

The abstract operation ToBoolean takes argument argument. It converts argument to a value of type Boolean according to Table 11:

Table 11: ToBoolean Conversions
Argument Type Result
Undefined Return false.
Null Return false.
Boolean Return argument.
Number If argument is +0𝔽, -0𝔽, or NaN, return false; otherwise return true.
String If argument is the empty String (its length is 0), return false; otherwise return true.
Symbol Return true.
BigInt If argument is 0, return false; otherwise return true.
Object Return true. Note

An alternate algorithm related to the [[IsHTMLDDA]] internal slot is mandated in section B.3.7.1.

7.1.3 ToNumeric ( value )

The abstract operation ToNumeric takes argument value. It returns value converted to a Number or a BigInt. It performs the following steps when called:

  1. Let primValue be ? ToPrimitive(value, number).
  2. If Type(primValue) is BigInt, return primValue.
  3. Return ? ToNumber(primValue).

7.1.4 ToNumber ( argument )

The abstract operation ToNumber takes argument argument. It converts argument to a value of type Number according to Table 12:

Table 12: ToNumber Conversions
Argument Type Result
Undefined Return NaN.
Null Return +0𝔽.
Boolean If argument is true, return 1𝔽. If argument is false, return +0𝔽.
Number Return argument (no conversion).
String See grammar and conversion algorithm below.
Symbol Throw a TypeError exception.
BigInt Throw a TypeError exception.
Object

Apply the following steps:

  1. Let primValue be ? ToPrimitive(argument, number).
  2. Return ? ToNumber(primValue).

7.1.4.1 ToNumber Applied to the String Type

ToNumber applied to Strings applies the following grammar to the input String interpreted as a sequence of UTF-16 encoded code points (6.1.4). If the grammar cannot interpret the String as an expansion of StringNumericLiteral, then the result of ToNumber is NaN.

Note 1

The terminal symbols of this grammar are all composed of characters in the Unicode Basic Multilingual Plane (BMP). Therefore, the result of ToNumber will be NaN if the string contains any leading surrogate or trailing surrogate code units, whether paired or unpaired.

Syntax

StringNumericLiteral ::: StrWhiteSpaceopt StrWhiteSpaceopt StrNumericLiteral StrWhiteSpaceopt StrWhiteSpace ::: StrWhiteSpaceChar StrWhiteSpaceopt StrWhiteSpaceChar ::: WhiteSpace LineTerminator StrNumericLiteral ::: StrDecimalLiteral NonDecimalIntegerLiteral[~Sep] StrDecimalLiteral ::: StrUnsignedDecimalLiteral + StrUnsignedDecimalLiteral - StrUnsignedDecimalLiteral StrUnsignedDecimalLiteral ::: Infinity DecimalDigits[~Sep] . DecimalDigits[~Sep]opt ExponentPart[~Sep]opt . DecimalDigits[~Sep] ExponentPart[~Sep]opt DecimalDigits[~Sep] ExponentPart[~Sep]opt

All grammar symbols not explicitly defined above have the definitions used in the Lexical Grammar for numeric literals (12.8.3)

Note 2

Some differences should be noted between the syntax of a StringNumericLiteral and a NumericLiteral:

7.1.4.1.1 Runtime Semantics: MV

The conversion of a String to a Number value is similar overall to the determination of the Number value for a numeric literal (see 12.8.3), but some of the details are different, so the process for converting a String numeric literal to a value of Number type is given here. This value is determined in two steps: first, a mathematical value (MV) is derived from the String numeric literal; second, this mathematical value is rounded as described below. The MV on any grammar symbol, not provided below, is the MV for that symbol defined in 12.8.3.1.

Once the exact MV for a String numeric literal has been determined, it is then rounded to a value of the Number type. If the MV is 0, then the rounded value is +0𝔽 unless the first non white space code point in the String numeric literal is -, in which case the rounded value is -0𝔽. Otherwise, the rounded value must be the Number value for the MV (in the sense defined in 6.1.6.1), unless the literal includes a StrUnsignedDecimalLiteral and the literal has more than 20 significant digits, in which case the Number value may be either the Number value for the MV of a literal produced by replacing each significant digit after the 20th with a 0 digit or the Number value for the MV of a literal produced by replacing each significant digit after the 20th with a 0 digit and then incrementing the literal at the 20th digit position. A digit is significant if it is not part of an ExponentPart and

  • it is not 0; or
  • there is a non-zero digit to its left and there is a non-zero digit, not in the ExponentPart, to its right.

7.1.5 ToIntegerOrInfinity ( argument )

The abstract operation ToIntegerOrInfinity takes argument argument. It converts argument to an integer, +∞, or -∞. It performs the following steps when called:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0𝔽, or -0𝔽, return 0.
  3. If number is +∞𝔽, return +∞.
  4. If number is -∞𝔽, return -∞.
  5. Let integer be floor(abs((number))).
  6. If number < +0𝔽, set integer to -integer.
  7. Return integer.

7.1.6 ToInt32 ( argument )

The abstract operation ToInt32 takes argument argument. It converts argument to one of 232 integral Number values in the range 𝔽(-231) through 𝔽(231 - 1), inclusive. It performs the following steps when called:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0𝔽, -0𝔽, +∞𝔽, or -∞𝔽, return +0𝔽.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs((number))).
  4. Let int32bit be int modulo 232.
  5. If int32bit ≥ 231, return 𝔽(int32bit - 232); otherwise return 𝔽(int32bit).
Note

Given the above definition of ToInt32:

  • The ToInt32 abstract operation is idempotent: if applied to a result that it produced, the second application leaves that value unchanged.
  • ToInt32(ToUint32(x)) is the same value as ToInt32(x) for all values of x. (It is to preserve this latter property that +∞𝔽 and -∞𝔽 are mapped to +0𝔽.)
  • ToInt32 maps -0𝔽 to +0𝔽.

7.1.7 ToUint32 ( argument )

The abstract operation ToUint32 takes argument argument. It converts argument to one of 232 integral Number values in the range +0𝔽 through 𝔽(232 - 1), inclusive. It performs the following steps when called:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0𝔽, -0𝔽, +∞𝔽, or -∞𝔽, return +0𝔽.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs((number))).
  4. Let int32bit be int modulo 232.
  5. Return 𝔽(int32bit).
Note

Given the above definition of ToUint32:

  • Step 5 is the only difference between ToUint32 and ToInt32.
  • The ToUint32 abstract operation is idempotent: if applied to a result that it produced, the second application leaves that value unchanged.
  • ToUint32(ToInt32(x)) is the same value as ToUint32(x) for all values of x. (It is to preserve this latter property that +∞𝔽 and -∞𝔽 are mapped to +0𝔽.)
  • ToUint32 maps -0𝔽 to +0𝔽.

7.1.8 ToInt16 ( argument )

The abstract operation ToInt16 takes argument argument. It converts argument to one of 216 integral Number values in the range 𝔽(-215) through 𝔽(215 - 1), inclusive. It performs the following steps when called:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0𝔽, -0𝔽, +∞𝔽, or -∞𝔽, return +0𝔽.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs((number))).
  4. Let int16bit be int modulo 216.
  5. If int16bit ≥ 215, return 𝔽(int16bit - 216); otherwise return 𝔽(int16bit).

7.1.9 ToUint16 ( argument )

The abstract operation ToUint16 takes argument argument. It converts argument to one of 216 integral Number values in the range +0𝔽 through 𝔽(216 - 1), inclusive. It performs the following steps when called:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0𝔽, -0𝔽, +∞𝔽, or -∞𝔽, return +0𝔽.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs((number))).
  4. Let int16bit be int modulo 216.
  5. Return 𝔽(int16bit).
Note

Given the above definition of ToUint16:

  • The substitution of 216 for 232 in step 4 is the only difference between ToUint32 and ToUint16.
  • ToUint16 maps -0𝔽 to +0𝔽.

7.1.10 ToInt8 ( argument )

The abstract operation ToInt8 takes argument argument. It converts argument to one of 28 integral Number values in the range -128𝔽 through 127𝔽, inclusive. It performs the following steps when called:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0𝔽, -0𝔽, +∞𝔽, or -∞𝔽, return +0𝔽.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs((number))).
  4. Let int8bit be int modulo 28.
  5. If int8bit ≥ 27, return 𝔽(int8bit - 28); otherwise return 𝔽(int8bit).

7.1.11 ToUint8 ( argument )

The abstract operation ToUint8 takes argument argument. It converts argument to one of 28 integral Number values in the range +0𝔽 through 255𝔽, inclusive. It performs the following steps when called:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0𝔽, -0𝔽, +∞𝔽, or -∞𝔽, return +0𝔽.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs((number))).
  4. Let int8bit be int modulo 28.
  5. Return 𝔽(int8bit).

7.1.12 ToUint8Clamp ( argument )

The abstract operation ToUint8Clamp takes argument argument. It converts argument to one of 28 integral Number values in the range +0𝔽 through 255𝔽, inclusive. It performs the following steps when called:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, return +0𝔽.
  3. If (number) ≤ 0, return +0𝔽.
  4. If (number) ≥ 255, return 255𝔽.
  5. Let f be floor((number)).
  6. If f + 0.5 < (number), return 𝔽(f + 1).
  7. If (number) < f + 0.5, return 𝔽(f).
  8. If f is odd, return 𝔽(f + 1).
  9. Return 𝔽(f).
Note

Unlike the other ECMAScript integer conversion abstract operation, ToUint8Clamp rounds rather than truncates non-integral values and does not convert +∞𝔽 to +0𝔽. ToUint8Clamp does “round half to even” tie-breaking. This differs from Math.round which does “round half up” tie-breaking.

7.1.13 ToBigInt ( argument )

The abstract operation ToBigInt takes argument argument. It converts argument to a BigInt value, or throws if an implicit conversion from Number would be required. It performs the following steps when called:

  1. Let prim be ? ToPrimitive(argument, number).
  2. Return the value that prim corresponds to in Table 13.
Table 13: BigInt Conversions
Argument Type Result
Undefined Throw a TypeError exception.
Null Throw a TypeError exception.
Boolean Return 1n if prim is true and 0n if prim is false.
BigInt Return prim.
Number Throw a TypeError exception.
String
  1. Let n be ! StringToBigInt(prim).
  2. If n is NaN, throw a SyntaxError exception.
  3. Return n.
Symbol Throw a TypeError exception.

7.1.14 StringToBigInt ( argument )

Apply the algorithm in 7.1.4.1 with the following changes:

  • Replace the StrUnsignedDecimalLiteral production with DecimalDigits to not allow Infinity, decimal points, or exponents.
  • If the MV is NaN, return NaN, otherwise return the BigInt which exactly corresponds to the MV, rather than rounding to a Number.

7.1.15 ToBigInt64 ( argument )

The abstract operation ToBigInt64 takes argument argument. It converts argument to one of 264 BigInt values in the range (-263) through (263-1), inclusive. It performs the following steps when called:

  1. Let n be ? ToBigInt(argument).
  2. Let int64bit be (n) modulo 264.
  3. If int64bit ≥ 263, return (int64bit - 264); otherwise return (int64bit).

7.1.16 ToBigUint64 ( argument )

The abstract operation ToBigUint64 takes argument argument. It converts argument to one of 264 BigInt values in the range 0 through the BigInt value for (264-1), inclusive. It performs the following steps when called:

  1. Let n be ? ToBigInt(argument).
  2. Let int64bit be (n) modulo 264.
  3. Return (int64bit).

7.1.17 ToString ( argument )

The abstract operation ToString takes argument argument. It converts argument to a value of type String according to Table 14:

Table 14: ToString Conversions
Argument Type Result
Undefined Return "undefined".
Null Return "null".
Boolean

If argument is true, return "true".

If argument is false, return "false".

Number Return ! Number::toString(argument).
String Return argument.
Symbol Throw a TypeError exception.
BigInt Return ! BigInt::toString(argument).
Object

Apply the following steps:

  1. Let primValue be ? ToPrimitive(argument, string).
  2. Return ? ToString(primValue).

7.1.18 ToObject ( argument )

The abstract operation ToObject takes argument argument. It converts argument to a value of type Object according to Table 15:

Table 15: ToObject Conversions
Argument Type Result
Undefined Throw a TypeError exception.
Null Throw a TypeError exception.
Boolean Return a new Boolean object whose [[BooleanData]] internal slot is set to argument. See 20.3 for a description of Boolean objects.
Number Return a new Number object whose [[NumberData]] internal slot is set to argument. See 21.1 for a description of Number objects.
String Return a new String object whose [[StringData]] internal slot is set to argument. See 22.1 for a description of String objects.
Symbol Return a new Symbol object whose [[SymbolData]] internal slot is set to argument. See 20.4 for a description of Symbol objects.
BigInt Return a new BigInt object whose [[BigIntData]] internal slot is set to argument. See 21.2 for a description of BigInt objects.
Object Return argument.

7.1.19 ToPropertyKey ( argument )

The abstract operation ToPropertyKey takes argument argument. It converts argument to a value that can be used as a property key. It performs the following steps when called:

  1. Let key be ? ToPrimitive(argument, string).
  2. If Type(key) is Symbol, then
    1. Return key.
  3. Return ! ToString(key).

7.1.20 ToLength ( argument )

The abstract operation ToLength takes argument argument. It converts argument to an integral Number suitable for use as the length of an array-like object. It performs the following steps when called:

  1. Let len be ? ToIntegerOrInfinity(argument).
  2. If len ≤ 0, return +0𝔽.
  3. Return 𝔽(min(len, 253 - 1)).

7.1.21 CanonicalNumericIndexString ( argument )

The abstract operation CanonicalNumericIndexString takes argument argument. It returns argument converted to a Number value if it is a String representation of a Number that would be produced by ToString, or the string "-0". Otherwise, it returns undefined. It performs the following steps when called:

  1. Assert: Type(argument) is String.
  2. If argument is "-0", return -0𝔽.
  3. Let n be ! ToNumber(argument).
  4. If SameValue(! ToString(n), argument) is false, return undefined.
  5. Return n.

A canonical numeric string is any String value for which the CanonicalNumericIndexString abstract operation does not return undefined.

7.1.22 ToIndex ( value )

The abstract operation ToIndex takes argument value. It returns value argument converted to a non-negative integer if it is a valid integer index value. It performs the following steps when called:

  1. If value is undefined, then
    1. Return 0.
  2. Else,
    1. Let integerIndex be 𝔽(? ToIntegerOrInfinity(value)).
    2. If integerIndex < +0𝔽, throw a RangeError exception.
    3. Let index be ! ToLength(integerIndex).
    4. If ! SameValue(integerIndex, index) is false, throw a RangeError exception.
    5. Return (index).