在Chrome中,当字符串不包含年份时,为什么JavaScript默认为2001?
t = new Date('Monday, Jan 11')
Thu Jan 11 2001 00:00:00 GMT+0000 (Greenwich Mean Time)
编辑:fwiw,这种行为也可以在React Native 中看到
我发现这是一个有趣的问题,所以我深入研究了V8引擎的源代码,Chromium和Chrome(出现这种现象的浏览器(使用的javascript引擎来对这种奇怪的行为进行逆向工程。
我在日期分析器中找到了这个片段。h:
if (!is_iso_date_) {
if (Between(year, 0, 49))
year += 2000;
else if (Between(year, 50, 99))
year += 1900;
}
假设没有年份的日期不符合ISO,则将2000
或1900
添加到未定义的OPyear
中。这应该表明50
上方有一个断点,事实证明是真的:
// Tested in Chrome:
console.log(new Date('1 1 49').getFullYear()); // 2049
console.log(new Date('1 1 50').getFullYear()); // 1950
文件year
中更高的部分定义如下:
int year = 0; // Default year is 0 (=> 2000) for KJS compatibility.
KJS是WebKit采用的一个非常早期的javascript引擎,而WebKit又被分叉为Chromium,因此选择这个默认值似乎是出于与古代祖先引擎的兼容性未知的原因。不过,按照这个逻辑,年份应该默认为2000
,而不是2001
。事实证明,这可能就是我们的意图。
在同一文档中,出现以下代码段:
// Day and month defaults to 1.
while (index_ < kSize) {
comp_[index_++] = 1;
}
comp_
保持[day, month, year]
的默认值。根据注释判断,kSize
应该是3
,因此如果没有另外指定,则只有day
和month
将被设置为1
。
然而,kSize
是4
,因此循环也在year
部分上迭代。然后(如果未指定(将year
设置为1
,覆盖之前的int year = 0
语句。前面提到的条件开始了,year += 2000
发生了,您最终得到了2001
的奇数默认值。
我怀疑这是一个错误,但不能确定,因为解析不存在的日期的预期行为很难定义。无论如何,您可能应该更好地指定自己的默认年份。这就结束了这段关于V8引擎的遥远源代码的推测之旅。
如果传递了一个字符串,Date的构造函数将使用Date.parse((,它是:
摘录:
ECMAScript规范指出:如果String不符合标准格式,则函数可能会退回到任何特定于实现的启发式或特定于实施的解析算法。无法识别的字符串或ISO格式字符串中包含非法元素值的日期将导致Date.parse((返回NaN。
然而,根据浏览器和提供的值,未被识别为ECMA-262定义的简化ISO格式的日期字符串中的无效值可能会也可能不会导致NaN,例如:
// Non-ISO string with invalid date values
new Date('23/25/2014');
在Firefox 30中将被视为2015年11月25日的本地日期,在Safari 7中则被视为无效日期。
所以答案是两者的结合,因为你执行的浏览器决定了这一点,而且这不是一个标准,所以浏览器可能会返回任何东西。
这是由您的浏览器完成的,您可能正在使用Crome。使用其他浏览器,您也可以获得无效日期。