比較 JavaScript 日期對(duì)象也能踩坑?漲姿勢(shì)了
直覺(jué)上,兩個(gè)相同的日期之間比較應(yīng)該是相等的,然而結(jié)果并不是這樣:
const?d1?=?new?Date('2019-06-01');
const?d2?=?new?Date('2018-06-01');
const?d3?=?new?Date('2019-06-01');
d1?===?d3;?//?false
d1?==?d3;?//?false
可以看到,無(wú)論用===還是==,結(jié)果都是false。細(xì)想也不奇怪,畢竟是兩個(gè)獨(dú)立的 JS 對(duì)象,并不是基本數(shù)據(jù)類型的變量。那該怎么判斷日期是否相等呢?
可以用toString()或者valueOf()。日期對(duì)象的toString()方法將日期轉(zhuǎn)成 ISO 日期字符串形式,而valueOf()?方法則將日期轉(zhuǎn)成毫秒數(shù)字形式的時(shí)間戳。
const?d1?=?new?Date('2019-06-01');
const?d2?=?new?Date('2018-06-01');
const?d3?=?new?Date('2019-06-01');
//?Sat?Jun?01?2019?08:00:00?GMT+0800?(中國(guó)標(biāo)準(zhǔn)時(shí)間)
d1.toString();
d1.valueOf();?//?1559347200000
d1.toString()?===?d2.toString();?//?false
d1.toString()?===?d3.toString();?//?true
d1.valueOf()?===?d2.valueOf();?//?false
d1.valueOf()?===?d3.valueOf();?//?true
有意思的是,雖然==?和?===?不能用來(lái)比較日期對(duì)象,<?和>?卻可以:
d1?//?false
d1?//?false
d2?//?true
因此,要判斷日期a是否在日期?b之前,只要判斷a < b是否為true。另外,日期之間還能用-操作符相減,返回毫秒差值。
const?d1?=?new?Date('2019-06-01');
const?d2?=?new?Date('2018-06-01');
const?d3?=?new?Date('2019-06-01');
d1?-?d3;?//?0
d1?-?d2;?//?1?年的毫秒數(shù),?1000?*?60?*?60?*?24?*?365
也就是說(shuō),你可以用a - b?結(jié)果的正負(fù)來(lái)判斷兩個(gè)日期的先后。
數(shù)組排序的坑
日期對(duì)象數(shù)組排序的結(jié)果很可能出乎意料。比如下面這個(gè)排序:
const?d1?=?new?Date('2017-06-01');
const?d2?=?new?Date('2018-06-01');
const?d3?=?new?Date('2019-06-01');
[d2,?d1,?d3].sort();?//?[d2,?d3,?d1]
按理說(shuō)從小到大排序應(yīng)該是[d1, d2, d3],結(jié)果很意外。這是為什么呢?原來(lái),JavaScript 數(shù)組的sort方法默認(rèn)是比較元素的字符串形式。因此,上面的sort實(shí)際上是基于下面的結(jié)果來(lái)排序的:
[?'Fri?Jun?01?2018?08:00:00?GMT+0800?(中國(guó)標(biāo)準(zhǔn)時(shí)間)',
??'Sat?Jun?01?2019?08:00:00?GMT+0800?(中國(guó)標(biāo)準(zhǔn)時(shí)間)',
??'Thu?Jun?01?2017?08:00:00?GMT+0800?(中國(guó)標(biāo)準(zhǔn)時(shí)間)'?]
怎么解決這個(gè)問(wèn)題?很簡(jiǎn)單,傳一個(gè)自定義的排序函數(shù)compare()給sort()方法。這個(gè)compare()函數(shù)的返回值確定了兩個(gè)元素的大?。ㄏ群箜樞颍?/p>
0?表示?a?和b?相等正值表示?
a > b,也就是a在b后面負(fù)值表示?
a < b,也就是a在b前面
由于 JavaScript 日期對(duì)象可以直接相減,那這個(gè)比較函數(shù)就很簡(jiǎn)單了:
const?d1?=?new?Date('2017-06-01');
const?d2?=?new?Date('2018-06-01');
const?d3?=?new?Date('2019-06-01');
[d2,?d1,?d3].sort((a,?b)?=>?a?-?b);?//?[d1,?d2,?d3]
下次碰到數(shù)組數(shù)組默認(rèn)排序出現(xiàn)這樣的結(jié)果你也就不感到奇怪了:
const?a?=?[1,?4,?3,?12];
a.sort();?//?[1,?12,?3,?4]
所以為了防止出現(xiàn) Bug,應(yīng)該傳入自定義排序函數(shù)。
