开胃菜
先说一个题外话,我在工作中碰到一个题目,须要比较 "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"
比较才能够。
这个题目就说到这里,人人有其他的要领能够留言补充,给人人供应差别的思绪。开胃菜完毕,进入正题。
正题
作为一个爱(记)学(不)习(清)的好(笨)孩子,经由过程字符串比较这件事,我意想到另有更多的非雷同范例的比较,比方字符串和数字的比较,布尔和数组的比较(我疯了么我这么用),别的另有加减乘除等其他操作符。
我以为有必要整顿一下了。
我第一反应是这张图:
真是诱人的笑颜呢 :)
在比较之前,我们须要先了解下种种数据范例转化的效果有哪些。
转数字
字符串:
- 空字符串是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]"
- 假如对象有
转布尔
- 一切的假值(
undefined
、null
、+0
、-0
、NaN
、""
)会被转化为false
,其他都邑被转为true
- 所以,空对象、空数组都是
true
转对象
-
null
和undefined
转对象直接抛非常 - 基本范例经由过程挪用
String()
、Number()
、Boolean()
组织函数,转换为他们各自的包装对象
运用场景
知道了种种数据范例转化的划定规矩,那末在差别的场景中,究竟是怎样运用的呢?
== 运算符
罕见的误区是:==
搜检值是不是相称,===
搜检值和范例是不是相称。
准确的诠释是:==
许可在相称比较中举行强迫范例转换,而===
不许可。
事实上,==
和===
都邑搜检操作数的范例,区分在于范例差别时它们的处置惩罚方式差别。
- 假如一个值是
null
,另一个值是undefined
,则相称 - 假如一个是字符串,另一个值是数字,则把字符串转换成数字,举行比较
- 假如恣意值是
true
,则把true
转换成1再举行比较;假如恣意值是false
,则把false
转换成0再举行比较 假如一个是对象,另一个是数值或字符串,把对象转换成基本范例的值再比较
- 对象转基本范例时,优先挪用
valueOf()
,再挪用toString()
。 - 破例的是
Date
,Date
应用的是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 | 正则的文本示意 | 正则自身 |
以上是本篇文章的内容,迎接人人提出本身的主意,我们一同进修提高,与君共勉。