【JS基本】范例转换知多少

开胃菜

先说一个题外话,我在工作中碰到一个题目,须要比较 "08:00""09:00" 的大小,末了我找到三种要领:

  • 在两个字符串前后各拼接雷同的年月日和秒,拼成完全的时刻花样举行比较:
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

看到这里预计有人就疑惑了,很明显第三种要领是更简约的,然则字符串比较,彷佛很少见,它比较的依据是什么呢?

实在,字符串比较大小,会从左到右顺次取两个字符串中的字符,两两比较他们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"

这里有一个题目就是,时刻花样必需保持一致,位数不够的记得补"0",拿"8:00""10:00"比较会发明效果有题目,必需拿"08:00""10:00"比较才能够。

这个题目就说到这里,人人有其他的要领能够留言补充,给人人供应差别的思绪。开胃菜完毕,进入正题。

正题

作为一个爱(记)学(不)习(清)的好(笨)孩子,经由过程字符串比较这件事,我意想到另有更多的非雷同范例的比较,比方字符串和数字的比较,布尔和数组的比较(我疯了么我这么用),别的另有加减乘除等其他操作符。

我以为有必要整顿一下了。

我第一反应是这张图:
《【JS基本】范例转换知多少》

真是诱人的笑颜呢 :)

在比较之前,我们须要先了解下种种数据范例转化的效果有哪些。

转数字

  • 字符串:

    • 空字符串是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()的返回状况

范例toStringvalueOf
Object"[object 范例名]"对象自身
String字符串值字符串值
Number返回数值的字符串示意。还可返回以指定进制示意的字符串,默许10进制数字值
Boolean "true" / "false" Boolean
Array每一个元素转换为字符串,用英文逗号作为分隔符举行拼接数组自身
Date日期的文本示意,花样为Wed Jun 05 2019 18:22:32 GMT+0800 (中国标准时刻)返回时刻戳,等同于挪用getTime()
Function函数的文本示意函数自身
RegExp正则的文本示意正则自身

以上是本篇文章的内容,迎接人人提出本身的主意,我们一同进修提高,与君共勉。

参考资料

    原文作者:诺顿
    原文地址: https://segmentfault.com/a/1190000019400646
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞