1、显示转换:
显示转换的方法Number、String、Boolean、parseInt、parseFloat、toString 等等

ToNumber

image.png
String 转换为 Number 类型的规则:

  1. 如果字符串中只包含数字,那么就转换为对应的数字。
  2. 如果字符串中只包含十六进制格式,那么就转换为对应的十进制数字。
  3. 如果字符串为空,那么转换为0。
  4. 如果字符串包含上述之外的字符,那么转换为 NaN。

ToBoolean

image.png
Symbol可以转换为true

ToString

image.png

常见面试题:
为什么 [1, 2, 3].map(parseInt) 返回 [1,NaN,NaN]?
答:
map内部实际执行的为parseInt(1, 0)、parseInt(2, 1)、parseInt(3, 2),第几个item和index默认作为了parseInt的两个参数
parseInt(string, radix) 的参数radix必须介于2~36之间,而且字符串string中的数字不能大于radix才能正确返回数字结果值。
parseInt(‘1’,0) = 1
parseInt(‘2’,1) = NaN
parseInt(‘3’,2) = NaN
参考:https://blog.csdn.net/freshlover/article/details/19034079/

2、隐式类型转换
隐式类型转换一般是在涉及到运算符的时候才会出现的情况,比如我们将两个变量相加,或者比较两个变量是否相等。
2.1、判断相等类型转换表
image.png
总结一些转换规则:

  • 类型相等不进行转换
  • null和undefined之间相互相等,与其他类型都不相等
  • 转换为的类型可以为Number和String类型,优先级为Number > String
  • 两个基本类型转为都为ToNumber
  • 引用类型与String类型比较不转换,与其他基本类型比较基本类型都转换为Number类型
  • 引用类型发生转换使用ToPrimitive方法

看一下ToPrimitive的源码

  1. // 获取类型
  2. const getType = (obj) => {
  3. return Object.prototype.toString.call(obj).slice(8,-1);
  4. }
  5. // 是否为原始类型
  6. const isPrimitive = (obj) => {
  7. const types = ['String','Undefined','Null','Boolean','Number'];
  8. return types.indexOf(getType(obj)) !== -1;
  9. }
  10. const ToPrimitive = (input, preferredType) => {
  11. // 如果input是原始类型,那么不需要转换,直接返回
  12. if (isPrimitive(input)) {
  13. return input;
  14. }
  15. let hint = '',
  16. exoticToPrim = null,
  17. methodNames = [];
  18. // 当没有提供可选参数preferredType的时候,hint会默认为"default";
  19. if (!preferredType) {
  20. hint = 'default'
  21. } else if (preferredType === 'string') {
  22. hint = 'string'
  23. } else if (preferredType === 'number') {
  24. hint = 'number'
  25. }
  26. exoticToPrim = input.@@toPrimitive;
  27. // 如果有toPrimitive方法
  28. if (exoticToPrim) {
  29. // 如果exoticToPrim执行后返回的是原始类型
  30. if (typeof (result = exoticToPrim.call(O, hint)) !== 'object') {
  31. return result;
  32. // 如果exoticToPrim执行后返回的是object类型
  33. } else {
  34. throw new TypeError('TypeError exception')
  35. }
  36. }
  37. // 这里给了默认hint值为number,Symbol和Date通过定义@@toPrimitive方法来修改默认值
  38. if (hint === 'default') {
  39. hint = 'number'
  40. }
  41. return OrdinaryToPrimitive(input, hint)
  42. }
  43. const OrdinaryToPrimitive = (input, hint) => {
  44. let methodNames = null,
  45. result = null;
  46. if (typeof input !== 'object') {
  47. return;
  48. }
  49. // 这里决定了先调用toString还是valueOf
  50. if (hint === 'string') {
  51. methodNames = [input.toString, input.valueOf]
  52. } else {
  53. methodNames = [input.valueOf, input.toString]
  54. }
  55. for (let name in methodNames) {
  56. if (input[name]) {
  57. result = input[name]()
  58. if (typeof result !== 'object') {
  59. return result
  60. }
  61. }
  62. }
  63. throw new TypeError('TypeError exception')
  64. }

ToPrimitive方法解读:
参数:
@input为转换的对象
@preferredType为转换的类型,支持无、Number、String

  1. 判断input为基本类型直接返回
  2. 赋值传入的preferredType类型
  3. 判断引用类型是否有@@toPrimitive方法,如果有使用exoticToPrim.call获取对应的值。值为基本类型直接返回,否则报错
  4. 如果preferredType是无赋值为默认的Number类型
  5. 调用OrdinaryToPrimitive

OrdinaryToPrimitive方法解读:
参数:
@input为转换的对象
@hint为转换的类型,支持、Number、String

  1. 判断input不为引用类型直接返回
  2. (1)判断如果hint为String类型,先调用toString方法返回原始类型直接返回,否则调用valueOf方法判断是原始类型直接返回,否则报错。(2)判断如果hint为Number类型,先调用valueOf方法返回原始类型直接返回,否则调用toString方法判断是原始类型直接返回,否则报错

如果传入参数是string,也就是对象到字符串的转换,经过了如下步骤:

  • 如果对象中有toString()方法,则调用这个方法。如果它返回一个原始值(undefined、Boolean、Number、String、BigInt、Symbol 和 null),js将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。
  • 如果对象没有toString()方法,或者toString()没有返回一个原始值,那么js会调用valueOf()方法。如果返回值是原始值,js将这个值转换为字符串,并返回字符串结果。
  • 否则,js抛出一个类型错误异常。

image.png

如果传入参数是number/default,也就是对象到数字的转换,经过了如下步骤:
和上面有点不同,到数字的转换会先尝试使用valueOf()方法

  • 如果对象具有valueOf()方法,后者返回一个原始值,则js会将其转换为数字(如果需要的话)并返回这个数字。
  • 否则,如果对象具有toString()方法,返回一个原始值(字符串直接量),则js将其转换为数字类型,并返回这个数字。
  • 否则,js抛出一个类型错误异常

字符串连接符

+两边有一边是字符串,那这个+就是字符串连接符,它会把其他数据类型调用String()方法转成字符串然后拼接;

引用类型使用valueOf和toString转换

数组:
image.png
对象:
image.png
函数:
image.png

特殊的对象:日期对象自定义了toString和valueOf
image.png[

](https://zhuanlan.zhihu.com/p/85731460)
实例讲解:
image.png

1、[] == 0
(1)[].valueOf() 得到[],还是引用类型继续转换
(2)[].toString() 得到””
(3)判断对比的为0,使用Number(“”) == 0
(4)结果为true
2、![] == 0
(1)逻辑非优先级高于关系运算符,![]转换为false
(2)判断对比的为0,使用Number(false) == 0
(3)结果为true
3、[] == ![]
(1)右边![],逻辑非运算符优先级比较高,![]转换为false
(2)判断右边不为字符串先使用valueOf转换,[].valueOf() 得到[],还是引用类型继续转换
(3)[].toString() 得到””
(4)Number(“””) == Nunber(false)
(5)结果得到true
4、[] == []
(1)判断两边都为引用类型,不发生转换
(2)虽然都为空数组,但是对比的为内存地址
(3)结果为false
5、{} == !{}
(1)右边!{},逻辑非运算符优先级比较高,!{}转换为false
(2)判断右边不为字符串先使用valueOf转换,{}.valueOf() 得到{},还是引用类型继续转换
(3)[].toString() 得到”[object Object]”
(4)Number(“[object Object]”) == Number(false)
(5)结果为false
6、{} == {}
(1)判断两边都为引用类型,不发生转换
(2)虽然都为空对象,但是对比的为内存地址
(3)结果为false

image.png
7、date对象+
(1)判断是+走字符串拼接
(2)d.toString() 转换为美式日期字符串 + 1 字符串拼接
8、date对象-
(1)判断是-,转换为Number类型计算
(2)d.valueOf() 转换为时间戳 - 1 计算

image.png
9、字符串与任何类型+,任何类型都会转换为字符串类型
image.png
10、- * / 这类只能使用Number类型运算,所以转换为Number类型

image.png
11、111 < “b” || “b” > 111
(1)由于Number优先级比较高,所以”b”转换为Number
(2)Number(“b”)等于NaN
(3)NaN < 111得不出判断结果
(4)结果为false
12、”111” < “b”
(1)字符串比较使用.charCodeAt()比较字符串首个的Unicode编码值
(2)”111”.charCodeAt()为49,”b”.charCodeAt()为98
(3)结果为true
image.png
类似的情况,”a1212”.charCodeAt()为97,所以为true

image.png
字符串能转换成Number的,比较还是转换成Number去比较

==和===的区别:
==判断时会发生隐式转换、===判断时即判断值相等又判断类型相等
日常使用:不用==判断,会造成意图不明确不便于日后维护
参考链接:https://www.jianshu.com/p/6ac1397e944c

参考:
https://zhuanlan.zhihu.com/p/85731460
https://blog.csdn.net/freshlover/article/details/19034079/
https://juejin.cn/post/7013933952436011039#heading-6