【JS基础】类型转换知多少

开胃菜

先说一个题外话,我在工做中遇到一个问题,须要比较 "08:00""09:00" 的大小,最后我找到三种方法:html

  • 在两个字符串先后各拼接相同的年月日和秒,拼成完整的时间格式进行比较:
var head = "2016-01-01 "
var foot = ":00"

var time1 = head + "08:00" + foot //"2016-01-01 08:00:00"
var time2 = head + "09:00" + foot //"2016-01-01 09:00:00"

剩下的就不说了,比较两个完整的日期仍是很容易的。数组

  • 把两个字符串中的冒号去掉,转换成数字进行比较:
function timeToNumber(time) {
    let [head,foot] = time.split(":")
    return Number(head+foot)
}

var time1 = timeToNumber("08:00") //800
var time2 = timeToNumber("09:00") //900
  • 直接比较

对,你没有看错,直接比较两个字符串:函数

"08:00" > "09:00" //false

看到这里估计有人就纳闷了,很明显第三种方法是更简洁的,可是字符串比较,好像不多见,它比较的依据是什么呢?post

其实,字符串比较大小,会从左到右依次取两个字符串中的字符,两两比较他们charCodeAt()的结果,直到比较出大小就中止。好比:学习

var str1 = "a11"
var str2 = "a2"
// str1 和 str2 比较的时候,会先比较 str1[0] 和 str2[0],两个都是 "a",比较下一个
// str1[1] 是"1",charCodeAt()是49,str2[1] 是"2",结果是50,因此 str1[1] < str2[1],对比结束
// 最终结果 str1 < str2

同理,在比较"08:00""09:00"的时候,先比较两个"0",发现一致以后比较"8""9",因此"08:00" < "09:00"spa

这里有一个问题就是,时间格式必须保持一致,位数不够的记得补"0",拿"8:00""10:00"比较会发现结果有问题,必须拿"08:00""10:00"比较才能够。code

这个问题就说到这里,你们有其余的方法能够留言补充,给你们提供不一样的思路。开胃菜结束,进入正题。htm

正题

做为一个爱(记)学(不)习(清)的好(笨)孩子,经过字符串比较这件事,我意识到还有更多的非相同类型的比较,好比字符串和数字的比较,布尔和数组的比较(我疯了么我这么用),另外还有加减乘除等其余操做符。对象

我以为有必要整理一下了。blog

我第一反应是这张图:

真是迷人的笑容呢 :)

在比较以前,咱们须要先了解下各类数据类型转化的结果有哪些。

转数字

  • 字符串:

    • 空字符串是0
    • 字符串头尾有空格会忽略
    • 空格在中间,或者字符串中含有非数字类型字符,转换结果就是NaN
  • 布尔:true -> 1, false -> 0
  • undefined字: NaN
  • null: 0
  • 数组:

    • 空数组是0
    • 若是数组中有且只有一项是数字元素,转换为数字
    • 其余状况NaN
  • 对象:

    • 若是对象有valueOf()方法,就调用该方法。若是返回基本类型值,就将这个值转化为数字
    • 若是对象没有valueOf()方法或者该方法返回的不是基本类型值,就会调用该对象的toString()方法。若是存在且返回值是基本类型值,就转化为数字
    • 不然就报错
  • 函数:NaN

转字符串

  • undefined -> "undefined"
  • null ->"null"
  • true -> "true" / false ->"false"
  • 数字:极小和极大的数字使用指数形式,通常的状况你懂得
  • 对象:

    • 若是对象有toString()方法,就调用toString()方法。若是该方法返回基本类型值,就将这个值转化为字符串
    • 若是对象没有toString()方法或者该方法返回的不是基本类型值,就会调用该对象的valueOf()方法。若是存在且返回值是基本类型值,就转化为字符串
    • 不然就报错
    • 除非自行定义,不然toString()返回内部属性[[Class]]的值,如"[object Object]"

转布尔

  • 全部的假值(undefinednull+0-0NaN"")会被转化为 false,其余都会被转为true
  • 因此,空对象、空数组都是true

转对象

  • nullundefined转对象直接抛异常
  • 基本类型经过调用String()Number()Boolean()构造函数,转换为他们各自的包装对象

使用场景

知道了各类数据类型转化的规则,那么在不一样的场景中,到底是怎么使用的呢?

== 运算符

常见的误区是:==检查值是否相等,===检查值和类型是否相等。

正确的解释是:==容许在相等比较中进行强制类型转换,而===不容许。

事实上,=====都会检查操做数的类型,区别在于类型不一样时它们的处理方式不一样。

  1. 若是一个值是null,另外一个值是undefined,则相等
  2. 若是一个是字符串,另外一个值是数字,则把字符串转换成数字,进行比较
  3. 若是任意值是true,则把true转换成1再进行比较;若是任意值是false,则把false转换成0再进行比较
  4. 若是一个是对象,另外一个是数值或字符串,把对象转换成基础类型的值再比较

    • 对象转基础类型时,优先调用valueOf(),再调用toString()
    • 例外的是DateDate 利用的是toString()转换

经典题

[] == false // true
!![] // true

//缘由是 == 两边都转为数字进行比较,而不是 [] 转为布尔值与 false 比较

+ 运算符

+ 运算符能够做为一元运算符使用,此时的做用是将后边跟着的数据转为数字

+true // 1
+[] // 0
+new Date() //获取当前时间的Unix时间戳

在做为二元运算符使用时,+运算符比- * /运算符要复杂一些,由于其余的运算符都是处理数字的,而+运算符还能够处理字符串拼接。

  • 两边若是有字符串,另外一边会转化为字符串进行相加
  • 若是没有字符串,两边都会转化为数字进行相加,对象也根据前面的方法转化为数字
  • 若是其中的一个操做数是对象,则将对象转换成原始值,日期对象会经过 toString()方法进行转换,其余对象经过valueOf()方法进行转换,可是大多数都是不具有可用的valueOf()方法,因此仍是会经过toString()方法执行转换

简单来讲就是,若是+运算符的其中一个操做数是字符串(或者经过以上步骤能够获得字符串),那么就执行字符串拼接,不然执行数字加法。

经典题

!+[]+[]+![] //"truefalse"

//首先第一个 + 左边不是数值,因此它是一元运算符,将后边跟着的 [] 转化为数字 0
//同时,最后一个 [] 左边是 ! 运算符,将 [] 转化为布尔值并取反,为 false
//转化后的结果为 !0 + [] + false
//!0 结果为 true,[] 转化为 "",因此结果变为 true + "" + false
//由于 第一个 + 右边有字符串,因此变为"true" + false
//最终结果为 "truefalse"

条件判断

如下条件判断的语句,会发生隐式转换为布尔值的状况:

  • if()语句中的条件判断表达式
  • for(..; ..; ..)语句中的条件判断表达式
  • while()do .. while()
  • ? : 中的条件判断表达式
  • ||&&左边的操做数

补充:valueOf()和toString()

经常使用内置对象调用toString()valueOf()的返回状况

类型 toString valueOf
Object "[object 类型名]" 对象自己
String 字符串值 字符串值
Number 返回数值的字符串表示。还可返回以指定进制表示的字符串,默认10进制 数字值
Boolean "true" / "false" Boolean
Array 每一个元素转换为字符串,用英文逗号做为分隔符进行拼接 数组自己
Date 日期的文本表示,格式为Wed Jun 05 2019 18:22:32 GMT+0800 (中国标准时间) 返回时间戳,等同于调用getTime()
Function 函数的文本表示 函数自己
RegExp 正则的文本表示 正则自己

以上是本篇文章的内容,欢迎你们提出本身的想法,咱们一块儿学习进步,与君共勉。

参考资料

相关文章
相关标签/搜索