Javascript中奇怪的语法:'sth'+ +new Date

3

我正在阅读一个jQuery插件,发现了这个有趣的语法:

'sth'+ +new Date

它创建了一个数字字符串,作者用它作为唯一标识符:sth1237004731731
我很好奇这是什么语法,是否有相关的阅读资料?谢谢!

5
在这里:https://dev59.com/Y3VC5IYBdhLWcg3wpjB8“+”号在JavaScript中被用于日期计算。它可以将日期加上或减去一个指定的时间段,例如天数、小时数或分钟数,然后返回新的日期对象。 - madflow
谢谢!它解释得很清楚。这也是我讨厌JavaScript的原因之一 :) - Xun Yang
2个回答

6
它利用JavaScript类型转换的一些副作用来构建一个唯一标识符(可能是为了一个元素)。令人困惑的部分是+new Date。这里new Date(或new Date())返回一个Date对象。但在它前面放置一个+或一个-会强制JS解释器将此值转换为Number对象,而JS计算Date > Number的方法是通过返回时间戳(或getTime())。

因此,这段代码可以用以下方式表达:

var date = new Date(), // "Mon May 14 2012 10:03:58 GMT-0400 (EST)"
    timestamp = date.getTime(), // 1337004238612
    identifierString = "sth" + timestamp.toString();

你可能认为没有必要这么冗长,所以我个人可能会这样写:

var identifier = "sth" + (new Date()).getTime();

然而,如果你希望有人维护你的代码,请避免编写像你的例子那样的代码。如果它让你停下来了,很可能也会阻止其他很多人。编码风格不仅仅是为了向解释器表达意图,更是为了向人类开发者表达意图。如果代码在浏览器中可以正常工作,但在大多数经验丰富的开发人员脑海中出现语法错误,那么你做错了,简单明了。


感谢您的解释,@Andrew!我完全同意您的观点,在被无数神秘的例子搞糊涂之后。 - Xun Yang
我同意一元运算符“+”通常很晦涩,因为不多的人知道它。另一种选择是使用Number(expr)代替+expr。两者的行为完全相同,除了+expr将返回ToNumber(GetValue(expr)),而Number(expr)只返回ToNumber(expr)。在现实世界中,这意味着没有区别,因为GetValue主要用于内部(规范级别)目的。 - Reid
1
@Reid,我不知道。Date对象有一个特定的方法可以返回自一开始就存在的时间戳。最近,人们一直在寻找最绝对最小的编码表达式,这似乎总是升级到“副作用”领域,我认为这有点危险。它阻止了年轻程序员理解语言,并在更广泛的社区中产生了分歧(好像我们还需要更多)。JS是一种非常简单的语言(带有一些非常奇怪的怪癖),但如果这种情况继续下去,我们的代码将读起来像正则表达式。 - Andrew

5
这是一种有趣的一元 + 操作符的用法。基本上,您可以将此表达式分解为三个单独的部分,在二进制 + 操作符处进行拆分: "sth",然后是 +,最后是 +new Date
二进制 + 的第一个操作数只是一个通用的字符串字面量。第二个操作数使用 一元 + 操作符,如链接的标准所述,将其操作数转换为 Number
因为new操作符具有最高的优先级,所以它比一元运算符+“绑定得更紧”,这意味着new Date将首先被计算。因此,一元运算符+的操作数反过来是表达式new Date的结果。当然,new Date只是创建一个空白的Date对象。根据§ 15.9.3.3 new Date()

新构造对象的[[PrimitiveValue]]内部属性设置为标识当前时间的时间值(UTC)。

换句话说,new Date只是表示当前时间的Date对象。而+new Date将把一个空白的Date对象转换为数字。

简短回答

规范很长,难以理解。简而言之,+new Date 返回与当前时间相关联的UNIX时间戳。
长答案:遵循规范
长答案遵循规范,一元运算符+调用ToNumber(GetValue(expr)),其中expr是计算出的操作数。GetValue(dateObj)将简单地返回dateObj,因此表达式变为ToNumber(dateObj)ToNumber的结果取决于参数的类型。对于对象,它返回ToNumber(ToPrimitive(input argument, hint Number))ToPrimitive会调用Date对象的valueOf属性。它返回一个Number,这是与Date对象关联的时间值:最终,这就是我们要找的!然后它回到了链条上:ToNumber(num)只是返回num

当然,从那里开始,字符串"sth"+new Date的结果被连接在一起(如果您愿意,可以在规范中找到),这就给出了您要查找的结果。


感谢@Reid的深入解释!如果Stack允许的话,我也希望能将您的答案标记为已接受 :) - Xun Yang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接