对象转原始类型toPrimitive
JavaScript 对象转换到基本类型值时,会使用 ToPrimitive 算法
toPrimitive
是个抽象的操作 可通过使用Symbol.toPrimitive
自定义
// 伪代码 /** * toPrimitive * @param {Object} input 如果非object类型则直接返回 * @param {string} [preferredType] 首选类型,需装换的基本类型 **/ function toPrimitive(input, preferredType) { const exoticToPrim = input[Symbol.toPrimitive] if (exoticToPrim) { let hint if (!preferredType) { hint = 'default' } else { // 这里没有判断number 是因为 // Symbol.toPrimitive的hint 一定是 "number"、"string" 和 "default"中任意一个 hint = preferredType === 'string' ? 'string' : 'number' } const result = exoticToPrim(hint) if (typeof result !== 'object') { return result } throw new TypeError('error') } if (!preferredType) { preferredType = 'number' } return OrdinaryToPrimitive(input, preferredType) } 复制代码
toPrimitive
处理流程
如果input为Object类型时
如果没有指定需要装换的基本类型(
preferredType
),则让hint
为"default"如果装换的基本类型(
preferredType
)为string,则让hint
为"string"如果装换的基本类型(
preferredType
)为number,则让hint
为"number"调用
exoticToPrim
得到result
如果
result
不是Object类型则返回result
如果还是Object类型则抛出异常
TypeError
是否存在外部定义的
toPrimitive
(exoticToPrim
)? 这里指是否定义Symbol.toPrimitive
如果
exoticToPrim
定义了,则如果不存在
preferredType
则 把preferredType
当"number"处理调用
OrdinaryToPrimitive(input, preferredType)
的结果当返回值非object则直接return input
// 伪代码 /** * 默认toPrimitive * @param {Object} O 对象 * @param {string} hint 转的类型 **/ function OrdinaryToPrimitive(O, hint) { const methodNames = hint === 'string' ? ['toString', 'valueOf'] : ['valueOf', 'toString'] for (let i = 0; i < methodNames.length; i++) { let name = methodNames[i] if (typeof O[name] === 'function') { const result = O[name]() if (typeof result !== 'object') { return result } } } throw new TypeError('error') } 复制代码
OrdinaryToPrimitive
处理流程
如果
hint
为String则定义
methodNames
为 [toString, valueOf]否则
则定义
methodNames
为 [valueOf, toString]遍历
methodNames
, 对于每个元素声明为name
调用
method
结果定义为result
如果
result
不为Object
,则返回result
获取
O
内的name
定义为method
如果
method
为可调用的方法最后抛出异常
TypeError
作者:Stay hungry.Stay fooli
链接:https://juejin.cn/post/7022835394609692686