阅读 191

细节解读JS隐式类型转换(js强制类型转换和隐式类型转换)

ECMAScript7规范中的ToPrimitive抽象操作

引用类型转化为原始类型最核心的其实就是这个内部抽象方法,这一块理解了,后面在做题目巩固的时候思路就很清晰了

Symbol --- @@toPrimitive

Symbol有很多有名的符号,@@toPrimitive,也就是Symbol.toPrimitive,这是定义在Symbol对象上的一个属性。

ToPrimitive(input [, PreferredType])

该抽象操作接受一个参数input和一个可选的参数PreferredType。该抽象操作的目的是把参数input转化为非对象数据类型,也就是原始数据类型。如果input可以同时转化为多个原始数据,那么会优先参考PreferredType的值。转化过程参照下表:

参数input的数据类型结果
Undefined返回input自身
Null返回input自身
Boolean返回input自身
Number返回input自身
String返回input自身
Symbol返回input自身
Object执行下面的步骤
如果input的数据类型是对象,执行下述步骤:
  1. 如果没有传入PreferredType参数,让hint等于"default"

  2. 如果PreferredTypehint String,让hint等于"string"

  3. 如果PreferredTypehint Number,让hint等于"number"

  4. exoticToPrim等于GetMethod(input, @@toPrimitive),大概语义就是获取参数input@@toPrimitive方法;

  5. 如果exoticToPrim不是Undefined,那么:

    1. result等于Call(exoticToPrim, input, « hint »),大概语义就是执行exoticToPrim(hint)

    2. 如果result是原始数据类型,返回result

    3. 抛出类型错误的异常;

  6. 如果hint"default",让hint等于"number"

  7. 返回OrdinaryToPrimitive(input, hint)抽象操作的结果。

总结:

  1. 判断PreferredType,只要传的值不是string,最后统一算作number`

  2. @@toPrimitive方法优先级高于OrdinaryToPrimitive(input, hint),如果前者能返回原始类型那就不需要执行后面的操作了

  3. 如果@@toPrimitive方法不存在或者存在返回的值不是原始类型,继续执行OrdinaryToPrimitive(input, hint)操作

疑问:hint是什么?怎么传的?(继续往下看)

OrdinaryToPrimitive(O, hint)

O的数据类型是对象,hint的数据类型是字符串,并且hint的值要么是"string",要么是"number"。该抽象操作的步骤如下:

  1. 如果hint"string",让methodNames等于« "toString", "valueOf" »

  2. 如果hint"number",让methodNames等于« "valueOf", "toString" »

  3. 按顺序迭代列表methodNames,对于每一个迭代值name

    1. method等于Call(method, O),大概语义就是执行method()

    2. 如果result的类型不是对象,返回result

    3. method等于Get(O, name),大概语义就是获取对象Oname值对应的属性;

    4. 如果method可以调用,那么:

  4. 抛出类型错误的异常。

由上述操作步骤可知:

  • 通过ToPrimitive的步骤6可知,当没有提供可选参数PreferredType的时候,hint会默认为"number"

  • 通过ToPrimitive的步骤4可知,可以通过定义@@toPrimitive方法来覆盖默认行为,比如规范中定义的Date日期对象和Symbol符号对象都在原型上定义了@@toPrimitive方法。

总结:

  1. 如果hint"string",先执行toString,如果没有返回原始值继续执行valueOf方法

  2. 如果hint"number",先执行valueOf,如果没有返回原始值继续执行toString方法

hint

hint可以理解为根据场景自动判断更倾向于转换成string还是number,如果无法判断倾向于转化哪一个,就是default。下面我们来模拟一下转化过程中获取hint值的过程

const obj = {      [Symbol.toPrimitive](hint) {          console.log(`hint: ${hint}`);      }  };  const arr = [] arr[obj] // hint: string  复制代码

const obj = {      [Symbol.toPrimitive](hint) {          console.log(`hint: ${hint}`);      }  };  -obj // hint: number 复制代码

var a = [1, 2, 3] a[Symbol.toPrimitive] = function (hint) {     console.log(`hint: ${hint}`); } '' + a // hint: default 复制代码

总结:

1、引用类型转化的时候,先确定是否有@@toPrimitive方法,优先级高于OrdinaryToPrimitive(input, hint),如果前者能返回原始类型那就不需要执行后面的操作了

2、判断hint值

3、如果hint"string",先执行toString,如果没有返回原始值继续执行valueOf方法

4、如果hint"number",先执行valueOf,如果没有返回原始值继续执行toString方法


作者:今天砖有点烫手
链接:https://juejin.cn/post/7036670291044466695

 伪原创工具 SEO网站优化  https://www.237it.com/ 


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐