Исполняющая система ECMAScript производит автоматическое преобразование типов по мере необходимости. Чтобы разъяснить семантику определенных конструкций, полезно определить набор абстрактных операций преобразования. Эти абстрактные операции не являются частью языка. Они определяются в данной спецификации только как вспомогательные средства для определения семантики языка. Абстрактные операции преобразования полиморфны, то есть, они могут принимать значение любого языкового типа, но не типа спецификации.
Абстрактная операция ToPrimitive К примитиву принимает аргумент input входной и необязательный аргумент PreferredType Предпочтительный тип. Абстрактная операция ToPrimitive преобразует свой аргумент input в тип, не являющийся объектным. Если объект может быть преобразован более чем к одному примитивному типу, то для выбора может быть использована необязательная подсказка PreferredType. Преобразование производится в соответствии с Таблицей 10:
Входной тип |
Результат |
Undefined |
Результат равен аргументу input (без преобразования). |
Null |
Результат равен аргументу input (без преобразования). |
Boolean |
Результат равен аргументу input (без преобразования). |
Number |
Результат равен аргументу input (без преобразования). |
String |
Результат равен аргументу input (без преобразования). |
Object |
Возвращает значение по умолчанию для Object. Значение по умолчанию какого-либо объекта получается путем вызова внутреннего метода [[DefaultValue]] этого объекта, с передачей необязательной подсказки PreferredType. Описание поведения внутреннего метода [[DefaultValue]] для всех родных объектов ECMAScript приводится в данной спецификации в пункте 8.12.8. |
Абстрактная операция ToBoolean К булевому преобразует свой аргумент к значению типа Boolean в соответствии с Таблицей 11:
Тип аргумента |
Результат |
Undefined |
false |
Null |
false |
Boolean |
Результат равен входному аргументу (без преобразования). |
Number |
Результат false, если аргумент равен +0, −0 или NaN; в противном случае результат – true. |
String |
Результат false, если аргумент – пустая строка (длина строки равна нулю); в противном случае результат – true. |
Object |
true |
Абстрактная операция ToNumber К числу преобразует свой аргумент к значению типа Number в соответствии с Таблицей 12:
Тип аргумента |
Результат |
Undefined |
NaN |
Null |
+0 |
Boolean |
Результат равен 1, если аргумент – true. Результат равен +0, если аргумент – false. |
Number |
Результат равен входному аргументу (без преобразования). |
String |
См. грамматику и примечание ниже. |
Object |
Выполняются следующие шаги:
|
Когда ToNumber применяется к строке, эта абстрактная операция применяет к входной строке грамматику, описанную ниже. Если эта грамматика не может интерпретировать строку как развертывание StringNumericLiteral Строковый числовой литерал, то результатом ToNumber будет NaN.
StringNumericLiteral :::
StrWhiteSpaceopt
StrWhiteSpaceoptStrNumericLiteral StrWhiteSpaceopt
StrWhiteSpace :::
StrWhiteSpaceChar StrWhiteSpaceopt
StrWhiteSpaceChar :::
WhiteSpace
LineTerminator
StrNumericLiteral :::
StrDecimalLiteral
HexIntegerLiteral
StrDecimalLiteral :::
StrUnsignedDecimalLiteral+
StrUnsignedDecimalLiteral-
StrUnsignedDecimalLiteral
StrUnsignedDecimalLiteral :::
Infinity
DecimalDigits .
DecimalDigitsoptExponentPartopt.
DecimalDigits ExponentPartopt
DecimalDigits ExponentPartopt
DecimalDigits :::
DecimalDigit
DecimalDigits DecimalDigit
DecimalDigit ::: один из
0 1 2 3 4 5 6 7 8 9
ExponentPart :::
ExponentIndicator SignedInteger
ExponentIndicator :::один из
e E
SignedInteger :::
DecimalDigits+
DecimalDigits-
DecimalDigits
HexIntegerLiteral :::
0x
HexDigit0X
HexDigit
HexIntegerLiteral HexDigit
HexDigit ::: один из
0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
Следует обратить внимание на некоторые различия между синтаксисом для StringNumericLiteral и синтаксисом для NumericLiteral (см. 7.8.3):
Перед StringNumericLiteral и/или после него может находиться пробел и/или символы окончания строки.
У десятичного StringNumericLiteral может быть любое количество цифр 0
в качестве первой цифры.
Перед десятичным StringNumericLiteral для обозначения его знака может находиться знак +
или -
.
Пустой или содержащий только пробельные символы StringNumericLiteral преобразуется к +0.
В целом, преобразование строки в числовое значение аналогично чтению значения типа Number из числового литерала (см. 7.8.3). Однако некоторые моменты отличаются, поэтому здесь мы полностью приводим процесс преобразования строкового числового литерала в значение типа Number. Это значение определяется в два этапа: сначала из строкового числового литерала выводится его математическое значение MV (сокращение от "mathematical value" – прим. перев.), а затем это MV округляется, как описано ниже:
MV StringNumericLiteral ::: [empty] равно 0.
MV StringNumericLiteral ::: StrWhiteSpace равно 0.
MV StringNumericLiteral ::: StrWhiteSpaceoptStrNumericLiteral StrWhiteSpaceopt равно MV StrNumericLiteral, независимо от наличия или отсутствия пробелов.
MV StrNumericLiteral ::: StrDecimalLiteral равно MV StrDecimalLiteral.
MV StrNumericLiteral ::: HexIntegerLiteral равно MV HexIntegerLiteral.
MV StrDecimalLiteral ::: StrUnsignedDecimalLiteral равно MV StrUnsignedDecimalLiteral.
MV StrDecimalLiteral ::: +
StrUnsignedDecimalLiteral равно MV StrUnsignedDecimalLiteral.
MV StrDecimalLiteral ::: -
StrUnsignedDecimalLiteral равно отрицательному MV StrUnsignedDecimalLiteral. (Обратите внимание, что если MV StrUnsignedDecimalLiteral Строковый беззнаковый десятичный литерал равно 0, то отрицательное значение этого MV тоже равно 0. Приведенное ниже правило округления производит преобразование этого беззнакового математического нуля к +0 или −0 (в зависимости от необходимости) с плавающей запятой).
MV StrUnsignedDecimalLiteral ::: Infinity
равно 1010000 (значению, настолько большому, что оно округляется до +∞).
MV StrUnsignedDecimalLiteral :::DecimalDigits.
равно MV DecimalDigits.
MV StrUnsignedDecimalLiteral :::DecimalDigits .
DecimalDigits равно MV первых DecimalDigits плюс (MV вторых DecimalDigits, умноженное на 10−n), где n – количество символов во вторых DecimalDigits.
MV StrUnsignedDecimalLiteral ::: DecimalDigits.
ExponentPart равно MV DecimalDigits, умноженному на 10e, где e – MV ExponentPart.
MV StrUnsignedDecimalLiteral ::: DecimalDigits.
DecimalDigits ExponentPart равно (MV первых DecimalDigits плюс (MV вторых DecimalDigits, умноженному на 10−n)) , умноженному на 10e, где n – количество символов во вторых DecimalDigits, а e – MV ExponentPart.
MV StrUnsignedDecimalLiteral :::.
DecimalDigits равно MV DecimalDigits, умноженному на 10–n, где n – количество символов в DecimalDigits.
MV StrUnsignedDecimalLiteral :::.
DecimalDigits ExponentPart равно MV DecimalDigits, умноженному на 10e–n, где n – количество символов в DecimalDigits, а e – MV ExponentPart.
MV StrUnsignedDecimalLiteral ::: DecimalDigits равно MV DecimalDigits.
MV StrUnsignedDecimalLiteral ::: DecimalDigits ExponentPart равно MV DecimalDigits, умноженному на 10e, где e – MV ExponentPart.
MV DecimalDigits ::: DecimalDigit равно MV DecimalDigit.
MV DecimalDigits ::: DecimalDigits DecimalDigit равно (MV DecimalDigits, умноженному на 10) плюс MV DecimalDigit.
MV ExponentPart ::: ExponentIndicator SignedInteger равно MV SignedInteger.
MVSignedInteger ::: DecimalDigitsis равно MV DecimalDigits.
MV SignedInteger ::: +
DecimalDigits равно MV DecimalDigits.
MV SignedInteger ::: -
DecimalDigits равно отрицательному MV DecimalDigits.
MV для DecimalDigit ::: 0
или для HexDigit ::: 0
равно 0.
MV для DecimalDigit ::: 1
или для HexDigit ::: 1
равно 1.
MV для DecimalDigit ::: 2
или для HexDigit ::: 2
равно 2.
MV для DecimalDigit ::: 3
или для HexDigit ::: 3
равно 3.
MV для DecimalDigit ::: 4
или для HexDigit ::: 4
равно 4.
MV для DecimalDigit ::: 5
или для HexDigit ::: 5
равно 5.
MV для DecimalDigit ::: 6
или для HexDigit ::: 6
равно 6.
MV для DecimalDigit ::: 7
или для HexDigit ::: 7
равно 7.
MV для DecimalDigit ::: 8
или для HexDigit ::: 8
равно 8.
MV для DecimalDigit ::: 9
или для HexDigit ::: 9
равно 9.
MV HexDigit ::: a
или для HexDigit ::: A
равно 10.
MV для HexDigit ::: b
или для HexDigit ::: B
является 11.
MV для HexDigit ::: c
или для HexDigit ::: C
является 12.
MV для HexDigit ::: d
или для HexDigit ::: D
является 13.
MV для HexDigit ::: e
или для HexDigit ::: E
является 14.
MV для HexDigit ::: f
или для HexDigit ::: F
является 15.
MV для HexIntegerLiteral ::: 0x
HexDigit равно MV HexDigit.
MV HexIntegerLiteral ::: 0X
HexDigit равно MV HexDigit.
MV HexIntegerLiteral ::: HexIntegerLiteral HexDigit равно (MV HexIntegerLiteral, умноженному на 16) плюс MV HexDigit.
После того, как точное MV строкового числового литерала определено, оно затем округляется до значения типа Number. Если MV равно 0, тогда округленное значение будет +0, за исключением случаев, когда первым непробельным символом в этом строковом числовом литерале является ‘-
’, и тогда округленное значение будет −0. В противном случае округленное значение должно представлять собой это числовое значение MV (в соответствии с определением в пункте 8.5), за исключением случаев, когда литерал включает StrUnsignedDecimalLiteral и имеет более 20 значимых чисел – в этом случае числовое значение может быть либо числовым значением MV литерала, полученного при замене на число 0 каждой значащей цифры после 20-й, либо числовым значением MV литерала, полученного в результате замены на число 0 каждой значащей цифры после 20-й, с последующим приращением литерала в позиции 20-й цифры. Цифра является значащей, если она не является частью ExponentPart Экспоненциальная часть, и
она не является 0; или
слева от нее находится ненулевая цифра, и справа от нее, не в ExponentPart, тоже находится ненулевая цифра.
Абстрактная операция ToInteger К целому преобразует свой аргумент к целочисленному значению. Она действует следующим образом:
Пусть number будет результатом вызова операции ToNumber для входного аргумента.
Если number – NaN, вернуть +0.
Если number равно +0, −0, +∞ или −∞, вернуть number.
Вернуть результат вычисления знак(number) * floor(abs(number)).
Абстрактная операция ToInt32 преобразует свой аргумент к одному из 232 целочисленных значений от −231 до 231−1 включительно. Она действует следующим образом:
Пусть number будет результатом вызова операции ToNumber для входного аргумента.
Если number равно NaN, +0, −0, +∞ или −∞, вернуть +0.
Пусть posInt Положительное целое число будет sign(number) * floor(abs(number)).
Пусть int32bit будет posInt modulo 232; то есть – конечным целочисленным значением k типа Number с положительным знаком и меньше 232 по модулю, таким образом, чтобы математическая разность между posInt и k была кратна 232.
Если int32bit больше или равно 231, вернуть int32bit − 232, в противном случае – вернуть int32bit.
ПРИМЕЧАНИЕ Принимая во внимание вышеуказанное определение ToInt32:
Абстрактная операция ToInt32 является идемпотентной: если она применяется к произведенному ею результату, это повторное применение не меняет полученного значения.
ToInt32(ToUint32(x)) равно ToInt32(x) для всех значений x. (Именно для сохранения этого последнего свойства +∞ и −∞ преобразуются к +0.)
ToInt32 преобразует −0 к +0.
Абстрактная операция ToUint32 преобразует свой аргумент к одному из 232 целочисленных значений от 0 до 232−1 включительно. Она действует следующим образом:
Пусть number будет результатом вызова операции ToNumber для входного аргумента.
Если number равно NaN, +0, −0, +∞ или −∞, вернуть +0.
Пусть int32bit будет posInt modulo 232; то есть – конечным целочисленным значением k типа Number с положительным знаком и меньше 232 по модулю, таким образом, чтобы математическая разность между posInt и k была математически кратна 232.
Вернуть int32bit.
ПРИМЕЧАНИЕ Принимая во внимание вышеуказанное определение ToUInt32:
Операция ToUint32 отличается от ToInt32 только шагом 5.
Абстрактная операция ToUint32 является идемпотентной: если она применяется к произведенному ею результату, это повторное применение не меняет полученного значения.
ToUint32(ToInt32(x)) равен ToUint32(x) для всех значений x. (Именно для сохранения этого последнего свойства +∞ и −∞ преобразуются к +0.)
ToUint32 преобразует −0 к +0.
Абстрактная операция ToUint16 преобразует свой аргумент к одному из 216 целочисленных значений от 0 до 216−1 включительно. Она действует следующим образом:
Пусть number будет результатом вызова ToNumber для входного аргумента.
Если number равно NaN, +0, −0, +∞ или −∞, то вернуть +0.
Пусть int16bit будет posInt modulo 216; то есть – конечным целочисленным значением k типа Number с положительным знаком и меньше 216 по модулю, таким образом, чтобы математическая разность между posInt и k была математически кратна 216.
Вернуть intint16bit.
ПРИМЕЧАНИЕ Принимая во внимание вышеуказанное определение ToUint16:
Единственная разница между операциями ToUint32 и ToUint16 заключается в замене 232 на 216 в шаге 4.
ToUint16 преобразует −0 к +0.
Абстрактная операция ToString К строке преобразует свой аргумент к значению типа String в соответствии с Таблицей 13:
Тип аргумента |
Результат |
Undefined |
|
Null |
|
Boolean |
Если аргумент true, то результат – Если аргумент false, то результат – |
Number |
См. пункт 9.8.1. |
String |
Вернуть входной аргумент (без преобразования). |
Object |
Выполняются следующие шаги: 1. Пусть primValue будет ToPrimitive(входной аргумент, подсказка String). 2. Вернуть ToString(primValue). |
Абстрактная операция ToString преобразует число к строковому формату следующим образом:
Если m равно NaN, вернуть строку "NaN"
.
Если m равно +0 или −0, вернуть строку "0"
.
Если m меньше нуля, вернуть строковую конкатенацию строки "-"
и ToString(−m).
Если m – бесконечность, вернуть строку "Infinity"
.
В противном случае, пусть n, k и s будут такими целыми числами, чтобы: k ≥ 1, 10k−1≤ s < 10k, значение Number для s × 10n−k равно m, а k являлось наименьшим возможным числом. Обратите внимание, что k – количество цифр в десятичном представлении s, что s не кратно 10, и что цифра самого младшего разряда в s не обязательно однозначно определяется этими критериями.
Если k ≤ n ≤ 21, вернуть строку, состоящую из k цифр десятичного представления s (по порядку, без начальных нулей), после которых следуют n−k экземпляров символа ‘0
’.
Если 0 < n ≤ 21, вернуть строку, состоящую из наиболее значимых n цифр десятичного представления s, после которых следует десятичная точка ‘.
’, после которой следуют оставшиеся k−n цифр десятичного представления s.
Если −6 < n ≤ 0, вернуть строку, состоящую из символа ‘0
’, после которого следует десятичная точка ‘.
’, после которой следуют −n экземпляров символа ‘0
’, после которых следует k цифр десятичного представления s.
В противном случае, если k = 1, вернуть строку, состоящую из одной цифры из s, после которой следует символ ‘e
’ в нижнем регистре, после которого следует знак плюс ‘+
’ или знак минус ‘−’ (в зависимости от того, является ли n−1 положительной или отрицательной величиной), за которой следует десятичное представление целого числа abs(n−1) (без начальных нулей).
Вернуть строку, состоящую из старшей цифры десятичного представления s, после которой следует десятичная точка ‘.’, за которой следуют остальные k−1 цифр десятичного представления s, после которых следует символ ‘e’ в нижнем регистре, после которого следует знак плюс ‘+’ или знак минус ‘−’ (в зависимости от того, является ли n−1 положительной или отрицательной величиной), после которого следует десятичное представление целого числа abs(n−1) (без начальных нулей).
ПРИМЕЧАНИЕ 1 Следующие наблюдения не являются нормативными требованиями настоящего Стандарта, но могут быть полезны в качестве руководящих принципов для реализаций:
Если x – любое числовое значение, кроме −0, то ToNumber(ToString(x)) имеет точно такое же числовое значение, что и x.
Младшая цифра s не всегда однозначно определена требованиями, указанными в шаге 5.
ПРИМЕЧАНИЕ 2 Для реализаций, обеспечивающих более точные преобразования, чем требуют вышеперечисленные правила, рекомендуется в качестве руководящего принципа использовать измененный вариант шага 5:
В противном случае, пусть n, k и s будут такими целыми числами, чтобы: k ≥ 1, 10k−1≤ s < 10k, значение Number для s × 10n−k равно m, а k являлось наименьшим возможным числом. Если для s есть несколько вариантов, выбрать значение s, для которого s × 10n−k является наиболее близким к значению m. Если таких возможных значений s два, выбрать то из них, которое является четным. Обратите внимание, что k – количество цифр в десятичном представлении s, и что s не кратно 10.
ПРИМЕЧАНИЕ 3 Создателям реализаций на ECMAScript советуем ознакомиться с работой и кодом по преобразованию чисел с плавающей точкой из двоичного формата в десятичный, написанными автором David M. Gay:
Gay, David M. Correctly Rounded Binary-Decimal and Decimal-Binary Conversions. Numerical Analysis, Manuscript 90-10. AT&T Bell Laboratories (Murray Hill, New Jersey). November 30, 1990. Эту работу можно найти по адресу
http://cm.bell-labs.com/cm/cs/doc/90/4-10.ps.gz. Используемые коды можно найти по адресу
http://cm.bell-labs.com/netlib/fp/dtoa.c.gz, или по адресу
http://cm.bell-labs.com/netlib/fp/g_fmt.c.gz, а также на различных зеркальных сайтах netlib
.
Абстрактная операция ToObject К объекту преобразует свой аргумент к значению типа Object в соответствии с Таблицей 14:
Тип аргумента |
Результат |
Undefined |
Сгенерировать исключение TypeError. |
Null |
Сгенерировать исключение TypeError. |
Boolean |
Создать новый объект Boolean, у которого внутреннему свойству [[PrimitiveValue]] присвоено значение аргумента. Описание объектов Boolean содержится в пункте 15.6. |
Number |
Создать новый объект Number, у которого внутреннему свойству [[PrimitiveValue]] присвоено значение аргумента. Описание объектов Number содержится в пункте 15.7. |
String |
Создать новый объект String, у которого внутреннему свойству [[PrimitiveValue]] присвоено значение аргумента. Описание объектов String содержится в пункте 15.5. |
Object |
Результат равен входному аргументу (без преобразования). |
Абстрактная операция CheckObjectCoercible Проверить приводимость к Object генерирует ошибку, если его аргумент имеет значение, которое невозможно привести к Object посредством операции ToObject. Определение этой операции приводится в Таблице 15.
Тип аргумента |
Результат |
Undefined |
Сгенерировать исключение TypeError. |
Null |
Сгенерировать исключение TypeError. |
Boolean |
Вернуть результат |
Number |
Вернуть результат |
String |
Вернуть результат |
Object |
Вернуть результат |
Абстрактная операция IsCallable Является вызываемым определяет, является ли аргумент, который должен иметь значение в языке ECMAScript, объектом функции в соответствии с Таблицей 16:
Тип аргумента |
Результат |
Undefined |
Вернуть false. |
Null |
Вернуть false. |
Boolean |
Вернуть false. |
Number |
Вернуть false. |
String |
Вернуть false. |
Object |
Если у объекта аргумента есть внутренний метод [[Call]], вернуть true, в противном случае вернуть false. |
Абстрактная операция внутреннего сравнения SameValue(x, y) ОдинаковоеЗначение(x, y), где x и y являются значениями ECMAScript, возвращает true или false. Это сравнение производится следующим образом:
Если Type(x) – Undefined, вернуть true.
Если Type(x) – Null, вернуть true.
Если Type(x) – Number, то
Если x – NaN и y – NaN, вернуть true.
Если x равно +0 и y равно -0, вернуть false.
Если x равно -0 и y равно +0, вернуть false.
Если x имеет такое же числовое значение, что и y, вернуть true.
Вернуть false.
Если Type(x) – String, то вернуть true, если x и y имеют абсолютно одинаковую последовательность символов (одинаковой длины и с одинаковыми символами в соответствующих позициях), иначе вернуть false.
Если Type(x) – Boolean, вернуть true, одновременно если x и y являются или true, или false; иначе вернуть false.
Вернуть true, если x и y относятся к одному и тому же объекту. Иначе вернуть false.