08. Object to Primitive
Бывают операции, при которых объект должен быть преобразован в примитив. Например:
Преобразование в строковый тип — если объект выводится через
alert(obj).Преобразование в численный тип — при арифметических операциях, сравнении с примитивом.
Преобразование в логический тип — при
if(obj)и других логических операциях.
Основные правила:
Любой объект в логическом контексте —
true, даже если это пустой массив[]или объект{}.Само преобразование выполняется по алгоритму
ToPrimitive.Если на объекте определен символ
@@toPrimitive, то вызывается он.Для объекта в строковом контексте вызывается метод
toString.Для численного преобразования объекта используется метод
valueOf, а если его нет — тоtoString.
Operation ToPrimitive
ToPrimitiveConverting an arbitrary value to a primitive is handled via the spec-internal operation ToPrimitive(input, ?PreferredType) takes an with input argument and an optional argument PreferredType which has three modes:
"number": the caller needs a number."string": the caller needs a string."default": the caller needs either a number or a string. The default mode is only used by:Equality operator (
==)Addition operator (
+)new Date(value)(exactly one parameter!)
If the value is a primitive then ToPrimitive() is already done. Otherwise, the value is an object obj, which is converted to a primitive as follows:
Number mode: Return the result of
obj.valueOf()if it is primitive. Otherwise, return the result ofobj.toString()if it is primitive. Otherwise, throw aTypeError.String mode: works like Number mode, but
toString()is called first,valueOf()second.Default mode: works exactly like Number mode.
toPrimitive operation in the spec
toPrimitive operation in the specThe abstract operation ToPrimitive 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. Conversion occurs according to the following algorithm:
If
Type(input)isObject, then:If
PreferredTypewas not passed, lethintbe"default".Else if
PreferredTypeis hintString, lethintbe"string".Else
PreferredTypeis hintNumber, lethintbe"number".Let
exoticToPrimbe ?GetMethod(input, @@toPrimitive).If
exoticToPrimis notundefined, thenLet
resultbeCall(exoticToPrim, input, hint).If
Type(result)is notObject, returnresult.Throw a
TypeErrorexception.
If hint is
"default", set hint to"number".Return
OrdinaryToPrimitive(input, hint).
Return
input.
When the abstract operation OrdinaryToPrimitive(O, hint) is called with arguments O and hint, the following steps are taken:
Assert:
Type(O)isObject.Assert:
Type(hint)isStringand its value is either"string"or"number".If
hintis"string", then:Let
methodNamesbe["toString", "valueOf"].
Else,
Let
methodNamesbe["valueOf", "toString"].
For each name in
methodNamesdoLet method be
Get(O, name).If
IsCallable(method)istrue, thenLet
resultbeCall(method, O).If
Type(result)is notObject, returnresult.
Throw a
TypeErrorexception.
Symbol @@toPrimitive
@@toPrimitiveSymbol.toPrimitive lets an object customize how it is coerced (converted automatically) to a primitive value. Значением этого символа должна быть функция, возвращающая значение одного из примитивных типов. Эта функция вызывается в качестве первой при преобразовании объекта в примитив по алгоритму ToPrimitive и имеет приоритет над другими функциями преобразования.
// An object without Symbol.toPrimitive property.
const obj1 = {};
console.log(+obj1); // NaN
console.log(`${obj1}`); // "[object Object]"
console.log(obj1 + ""); // "[object Object]"
// An object with Symbol.toPrimitive property.
const obj2 = {
[Symbol.toPrimitive](hint) {
if (hint === "number") {
return 10;
}
if (hint === "string") {
return "hello";
}
return true;
}
};
console.log(+obj2); // 10 -- hint is "number"
console.log(`${obj2}`); // "hello" -- hint is "string"
console.log(obj2 + ""); // "true" -- hint is "default"Operations toString and valueOf
toString and valueOfВсе объекты наследуют два метода преобразования:
Метод
toString()он возвращает строковое представление объекта. Если переменная является объектом, то по умолчанию методtoStringвыводит[object <Tип>]. Обратиться к этой нативной реализацииtoStringможноObject.prototype.toString.call(obj).Метод
valueOf(). Задача этого метода определена нечетко: предполагается, что он должен преобразовать объект в представляющее его простое значение, если такое значение существует. Объекты по своей природе являются составными значениями, и большинство объектов не могут быть представлены в виде единственного простого значения, поэтому по умолчанию методvalueOf()возвращает не простое значение, а сам объект (this). МетодvalueOfобязан возвращать примитивное значение, иначе его результат будет проигнорирован. При этом — не обязательно числовое.
> const empty = {};
> empty.toString() // => '[object Object]'
> const empty = {};
> empty.valueOf() === empty // => trueПримеры использования valueOf:
Классы-обертки определяют методы
valueOf(), возвращающие обернутые простые значения.Массивы, функции и регулярные выражения наследуют метод по умолчанию. Вызов метода
valueOf()экземпляров этих типов возвращает сам объект.Класс
Dateопределяет методvalueOf(), возвращающий дату во внутреннем представлении: количество миллисекунд, прошедших с 1 января 1970 года.
Last updated
Was this helpful?