1. toPrimitive

toPrimitive抽象操作用于将一个值转为原始值.这个操作没有对应的JavaScript API,但是它在Object类型的值进行toStringtoNumber操作时被使用.
toPrimitive操作接收2个参数,一个时要转换的值value,一个是偏好类型preferedType,取值有3种情况:default number string
具体转换规则如下面的代码所示:

  1. // https://tc39.es/ecma262/#sec-ordinarytoprimitive
  2. function ordinaryToPrimitive(value, hint) {
  3. const methodNames = hint === 'number' ? ['valueOf', 'toString'] : [['toString', 'valueOf']];
  4. for (const methodName of methodNames) {
  5. const result = value[methodName]?.();
  6. if (Object(result) !== result) return result;
  7. }
  8. throw new TypeError('can not transform');
  9. }
  10. // https://tc39.es/ecma262/#sec-toprimitive
  11. function toPrimivite(value, preferedType) {
  12. // 如果是原始值则不需要进行转换,直接返回
  13. if (Object(value) !== value) return value;
  14. if (value[Symbol.toPrimitive]) {
  15. const result = value[Symbol.toPrimitive](preferedType ?? 'default');
  16. if (Object(result) !== value) return result;
  17. throw new TypeError('can not transform');
  18. }
  19. return ordinaryToPrimitive(value, preferedType ?? 'number');
  20. }

对于 valueOf 和 toString 方法,它的调用结果需要具体对待。
valueOf 方法首先存在于 Object 的原型上,Object.prototype.valueOf 返回调用对象本身。原始值包装类型:Boolean,Number,String 重写了该方法,Wrapper.prototype.valueOf 返回包装对象的对应原始值。而对于 Date 实例而言,valueOf 方法返回一个整数,表示从 1970 年 1 月 1 日至今所经过的毫秒数。
toString 方法首先存在于 Object 的原型上,Object.prototype.toString 返回形如 [object tag] 的字符串。不过原始值包装类型:Boolean, Number, String 方法重写了该方法,Wrapper.prototype.toString 返回包装对象的对应原始值的字符串表示。Array 也重写了该方法,Array.prototype.toString 效果上等于 Array.prototype.join。Date 也重写了该方法,返回当前日期的表示。

2.toBoolean

toBoolean 操作是一个抽象的操作,它对应 JavaScript 中的 Boolean(value) 类型转换函数(或者 !! 操作符)。这个操作将一个任意值转换为 1 个 Boolean 类型的值(true 或 false 值)。

值的类型 true false
Undefined 和 Null undefined, null
Boolean true false
Number 非 0, -0, NaN 的 Number 值 0, -0, NaN
BigInt 非 0n, -0n 0n, -0n
String 非 ‘’ ‘’
Symbol 全部值
Object 全部值

如下面的代码所示:

  1. const { log } = console;
  2. const results = [undefined, null, false, 0, NaN, Infinity, -12n, '', Symbol('symbol'), {}].map(
  3. Boolean,
  4. );
  5. log(...results);
  6. // -> false false false false false true true false true true

3.toString

toString 抽象操作对应 JavaScript 的 String(value) 类型转换函数。它将一个任意值转换为一个 String 类型的值。

  • 原始类型

Undefined,Null,boolean,Number,BigInt,String,Symbol 这些原始类型会被转为对应的字符串表示,如下面的代码所示:

  1. const { log } = console;
  2. const results = [undefined, null, false, 0, NaN, Infinity, -12n, 'text', Symbol('symbol')].map(
  3. String,
  4. );
  5. log(...results);
  6. // -> 'undefined' 'null' 'false' '0' 'NaN' 'Infinity' '-12' 'text' 'Symbol(symbol)'
  • Object 类型

对于 Object 类型,String() 函数转换规则如下:

4.toNumber

toNumber 抽象操作用于将一个值转换为 Number 类型,它在 JavaScript 中的对应 API 是 Number() 类型转换函数。
toNumber 转换规则如下表所示:

值的类型 转换结果
Undefined NaN
Null 0
Boolean true => 1, false => 0
Number 直接返回
BigInt 报错
String 数值型字符串到数值,否则为 NaN
Symbol 报错
Object toNumber(toPrimitive(value, ‘number’))

上表值得说明的是,String 类型在转换时,字符串必须满足数值型字符串。否则转换结果就是 NaN。而 Object 类型的值在进行转换时,首先经过 toPrimitive 抽象操作转换为原始值,然后再根据上表进行转换。