JS - 隐式类型转换

一、ECMAScript数据类型

6种原始类型(基本数据类型)

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Symbol (ECMAScript 6)

Object (引用类型)

  • Object 类型
  • Array 类型
  • Date 类型
  • RegExp
  • 类型 Function 类型

原生类型内建的包装对象,包括:

  • String()
  • Number()
  • Boolean()
  • Array()
  • Object()
  • Function()
  • RegExp()
  • Date()
  • Symbol()
  • Error()

在操作原始数据类型的属性和方法时,JS会自动将原始类型转换成一个对应的包装对象。此时该对象就拥有了属于它本身的一系列属性和方法。所以当我们定义了一些基本数据类型,想访问其对应的属性或方法时,就需要将其转换为这个值的包装对象,然而现实中并不需要这么麻烦,这是因为JS运行的宿主对象(浏览器等)将会自动地包装基本类型值来满足这样的访问。
在这里插入图片描述

二、严格相等和宽松相等

相等操作符(==)比较两个值是否相等,在比较前将两个被比较的值转换为相同类型

全等操作符(===)比较两个值是否相等,两个被比较的值在比较前都不进行隐式类型转换。

抽象相等比较算法

在比较x == y,其中 x 和 y 是值,结果返回 true 或 false 。比较规则如下:

  1. 当 x 的类型与 y 的类型相同时:
a. 如果x的类型为Undefined,返回true。
b. 如果x的类型为Null,返回true。
c. 如果x的类型为Number,则如下:
    i.   如果 x 为 NaN, 返回 false.(NaN == NaN 为false)
    ii.  如果 y 为 NaN, 返回 false.	
    iii. 如果 x 和 y 的值相同, 返回 true.
    iv.  如果x为+0,y为−0,返回 true.
    v.   如果x为−0,y为+0,返回 true.
          其他返回 false.
d. 如果x是string类型,那么假如x和y是完全相同的字符序列(相同的长度和相应位置的相同字符),则返回true。否则,返回false。
e. 如果x是布尔类型,假如x和y都为true或都为false,则返回true。否则,返回false。
f. 如果x和y引用同一对象,则返回true。否则,返回false。

  1. x 和 y 类型不相同的情况:
  a. 如果x为null,y为undefined,则返回true。
  b. 如果x为undefined,y为null,则返回true。(其余的任何类型与undefined和null相比都为false)
  c. 如果x是数字类型,y是字符串类型,则返回x == ToNumber(y)的比较结果.
  d. 如果x是字符串类型,y是数字类型,则返回ToNumber(x) == y的比较结果.
  e. 如果x是布尔类型,则返回ToNumber(x)==y的比较结果.
  f. 如果y是布尔类型,则返回x == ToNumber(y)的比较结果.
  g. 如果x是字符串或数字类型,y 是对象类型,返回比较结果x== ToPrimitive(y)。
  h. 如果x是对象类型,y是字符串或数字类型,返回比较结果ToPrimitive(x)==y。
  i. 其他则返回false

上述规则看起来很复杂,但总结起来其实只有以下几点:

  1. 两个引用类型比较,只需判断它们是不是引用了同一个对象,是返回true,否则为false。
  2. undefined 和 null 两者互相比较或者与自身比较,结果是true。它俩与其他任何值比较的都为false。
  3. NaN与任何值比较包括它自身结果都是false。
  4. 引用类型和基本数据类型(String、Number)进行比较,引用类型会转换成与之所比较的基本数据的类型,再进行比较。
  5. 引用类型和基本数据类型(Boolean)进行比较,Boolean类型先转换为数字类型,引用类型再转换成与之所比较的基本数据的类型进行比较。
  6. String,Boolean,Number中的任意两个进行比较,最后都会转为Number类型再进行比较。
三、具体的类型转换过程
1. ToNumber

抽象操作ToNumber将非数字值转换为数字类型。

  • 布尔类型 true 转换为1,false 转换为0。
  • 字符串类型,""(空字符串)转为0,‘123’ 转为 123,‘123px’
    则被转为NaN(按照上述总结,NaN与任何类型比较都为false,此时就不需要再考虑其他情况)。
  • undefined 会转换为NaN,null 会转换为 0。(按上述总结第3条,null 和 undefined 跟其他任何非该两个类型中其一的比较都为false。结果容易得出,就不需要再考虑其他类型转换了)。
  • 引用类型,它们都需要先进行ToPrimitive转换为基本数据类型后再转换为数字类型。
2. ToPrimitive

抽象操作ToPrimitive将引用类型转为基本数据类型。

JS引擎内部转换为原始值ToPrimitive(obj,preferredType)函数接受两个参数,第一个obj为被转换的对象,第二个preferredType为希望转换成的类型(默认为空,接受的值为Number或String)

在执行ToPrimitive(obj,preferredType)时如果第二个参数为空并且obj为Date的实例时,此时preferredType会被设置为String,其他情况下preferredType都会被设置为Number如果preferredType为Number。
转换为Number数字类型的过程为首先调用obj.valueOf(),如果执行结果是基本数值类型就返回该值,否则就调用obj.toString(),返回该字符串类型值。
转换为String数字类型的过程为首先调用obj.toString(),如果执行结果是基本数值类型就返回该值,否则就调用obj.valueOf(),返回该字符串类型值。

上述规则总结起来基本就是:

  1. ToPrimitive转换为原始数据类型时,如果是基本数据类型就直接返回该类型值。
  2. 如果不是,则优先调用valueOf方法(如果有),看其返回结果是否是基本类型,如果是,则返回。否则,再调用toString方法,转换为字符串类型后返回。
  3. 当类型为Date日期类型时,JS希望其优先被转换成字符串类型,则先调用toString方法,转换为字符串。
  4. 其他情况报错。因为从ES5开始,使用Object.create(null)创建的对象由于没有原型链,自然就也没有valueOf()和toString()方法,这种情况出现的很少,基本可以忽略。

对象、数组、日期类型最后基本都被转换为字符串类型。所以我们姑且可以将ToPrimitive看做将引用类型最后都转换为字符串类型。

3.ToBoolean

抽象操作ToBoolean将转为布尔类型。
对于布尔类型转换来说,假值(undefined、null、false、+0、-0、NaN、"")会被转换为false,除假值外的所有值都会被转换成true。

4.ToString

抽象操作ToString将转为字符串类型。
对于字符串类型也比较好理解,大部分的基本数据类型转换为字符类型时,基本就是在它基础上加了引号这么直观,比较特殊的就是+0、0、-0它们几个都会被转成相同的’0’,还有那些极小和极大的数字将会转换为指数形式的字符串来表现,而引用类型转换成字符串的时候也跟它们ToPrimitive时候的规则一致(见上文ToPrimitive)。

四、 常见的隐式强制类型转换
  1. + - * / % 这几个运算符都可以将结果转为数字类型
  2. + 运算符常用来进行数字类型强制转换,因为它不会像**-**运算符一样影响结果
  3. + 运算符可以将日期类型new Date()转换成数字类型的时间戳
  4. ! 逻辑运算符可以将任何类型转为布尔类型,因为!运算符转换后的结果是被反转的,我们也可以使用两个!来得出正确的结果
  5. ** if()、 while() **括号内可以对所有数据类型默认执行强制布尔类型转换
  6. 三元运算符的条件也会执行强制布尔类型转换

参考链接
JavaScript中的隐式类型转换
全面分析toString与valueOf

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值