time返回的是什么_var now = +new Date(); 请问这里为什么要有个加号?

a141c4ec4a2d391e626f3ab9c15620d6.png

认真的小伙伴应该发现了,在上一章的代码里面高频出现了var now = +new Date()。那爱动脑筋的小伙伴就会问这里为什么要有个加号?这个加号又有什么作用呢?

简单的说,这个是转时间戳的方法

但是,真实的变化是什么样的呢?

这是隐式转换

我们先看看ECMAScript规范对一元运算符的规范:

一元+ 运算符

一元+运算符将其操作数转换为Number类型并反转其正负。注意负的+0产生-0,负的-0产生+0。

产生式 UnaryExpression : - UnaryExpression 按照下面的过程执行 :

  1. 令 expr 为解释执行 UnaryExpression 的结果 .
  2. 令 oldValue 为 ToNumber(GetValue(expr)).
  3. 如果 oldValue is NaN ,return NaN.
  4. 返回 oldValue 取负(即,算出一个数字相同但是符号相反的值)的结果。

+new Date()相当于 ToNumber(new Date())

我们再来看看ECMAScript规范对ToNumber的定义:

4eab04d98b00f934a562e4cb00ce56c1.png

我们知道new Date()是个对象,满足上面的ToPrimitive(),所以进而成了ToPrimitive(new Date())

接着我们再来看看ECMAScript规范对ToPrimitive的定义,一层一层来,抽丝剥茧。

05d43625cebb9e2fbd58257323be47f2.png

这个ToPrimitive可能不太好懂,我给你解释一下吧:

ToPrimitive(obj,preferredType)JS引擎内部转换为原始值ToPrimitive(obj,preferredType)函数接受两个参数 第一个obj为被转换的对象 第二个preferredType为希望转换成的类型(默认为空,接受的值为Number或String)在执行ToPrimitive(obj,preferredType)时如果第二个参数为空并且obj为Date的实例时,此时preferredType会被设置为String,其他情况下preferredType都会被设置为Number如果preferredType为Number,ToPrimitive执行过程如下:1. 如果obj为原始值,直接返回;2. 否则调用 obj.valueOf(),如果执行结果是原始值,返回之;3. 否则调用 obj.toString(),如果执行结果是原始值,返回之;4. 否则抛异常。如果preferredType为String,将上面的第2步和第3步调换,即:1. 如果obj为原始值,直接返回;2. 否则调用 obj.toString(),如果执行结果是原始值,返回之;3. 否则调用 obj.valueOf(),如果执行结果是原始值,返回之;4. 否则抛异常。
5779b87860008d7fc63092af5251a856.png

首先我们要明白 obj.valueOf() 和 obj.toString() 还有原始值分别是什么意思,这是弄懂上面描述的前提之一:

toString用来返回对象的字符串表示。

var obj = {};console.log(obj.toString()); // [object Object]var arr2 = [];console.log(arr2.toString()); // ""空字符串 var date = new Date();console.log(date.toString()); // Tue Jul 30 2019 09:44:17 GMT+0800 (中国标准时间)

valueOf方法返回对象的原始值,可能是字符串、数值或bool值等,看具体的对象。

var obj = { name: "obj"};console.log(obj.valueOf());//Object {name: "obj"}var arr1 = [1];console.log(arr1.valueOf());//[1]var date = new Date();console.log(date.valueOf());//1564451057792如代码所示,三个不同的对象实例调用valueOf返回不同的数据

原始值指的是['Null','Undefined','String','Boolean','Number','Symbol']6种基本数据类型之一

最后分解一下其中的过程:

+new Date():

1.运算符new的优先级高于一元运算符+,所以过程可以分解为:

var time=new Date();

+time

2.根据上面提到的规则相当于:ToNumber(time)

3.time是个日期对象,根据ToNumber的转换规则,所以相当于:ToNumber(ToPrimitive(time))

4.根据ToPrimitive的转换规则:ToNumber(time.valueOf()),time.valueOf()就是 原始值 得到的是个时间戳,假设time.valueOf()=1503479124652

5.所以ToNumber(1503479124652)返回值是1503479124652这个数字。

6.分析完毕,从原理得出结果,而不是从浏览器输出的结果来解释结果。用结论解释结论,会忽略很多细节

好了,到这里,大家应该对标题中的问题有了一个满意的答案了吧,但是也有细心的小伙伴发现了“问题”,既然“在执行ToPrimitive(obj,preferredType)时如果第二个参数为空并且obj为Date的实例时,此时preferredType会被设置为String",那么就会先调用obj.toString(),返回的就是一个字符串,那就和我们期望的时间戳不一样了

如果你心中有此一问,恭喜你,你马上会找到答案了

551eee5e0fa273fa00ab0125b33f6197.png

所以,你明白了吗?

参考文章:

https://github.com/jawil/blog/issues/5

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值