搜索

首页  >  问答  >  正文

javascript - typeof (new Date()) + 1 结果为啥是"string"确不是"number"

typeof (new Date()) + 1    // 结果为啥是"string"
typeof (new Date()) - 1    //"number"

console.log((new Date()) + 1);    //"Mon Feb 22 2016 14:13:27 GMT+0800 (中国标准时间)1"
console.log((new Date()) - 1);    //1456121787203

({valueOf:function(){return 3;},toString:function(){return 2;}}) + 1 //4
({valueOf:function(){return {};},toString:function(){return 5;}}) + 1 //6

console.log((new Date()) + 1);这行js代码,不是应该先调用 Date的valueOf(),如果valueOf()不返回简单类型,再调用Date的toString()的吗?
可事实上确实直接调用了toString()方法

伊谢尔伦伊谢尔伦2786 天前1151

全部回复(4)我来回复

  • 巴扎黑

    巴扎黑2017-04-10 17:12:23

    + 有两种含义,一个是字符串连接,一个是加法。所以js加法有点儿复杂。
    首先吧两边的数转换成基本类型,而转换成基本类型的时候默认先调用valueof,然后是toString,除了new Date类型之外。所以对于new Date 优先调用的是toString 。

    + 操作,如果其中一个是字符串的话,那么就认为是字符串链接。没有字符串才认为是数字的加法。

    -,就只有数字减法的意思,所以类型转换都是ToNumber 也就是说优先调用valuleOf

    下面的不想看就算了,跟上面一个意思。

    ECMAscript 标准摘录(修改过):
    对加法的描述:

    1. Let lprim be ToPrimitive(lval).

    2. Let rprim be ToPrimitive(rval).

    3. If Type(lprim) is String or Type(rprim) is String, then
      Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)

    4. Return the result of applying the addition operation to ToNumber(lprim) and ToNumber(rprim).

    减法:

    1. Let lnum be ToNumber(lval).

    2. Let rnum be ToNumber(rval).

    3. Return the result of applying the subtraction operation to lnum and rnum.

    ToNumber定义: ToPrimitive(input argument, hint Number)

    ToPrimitive定义:
    When the ToPrimitive internal method of O is called with no hint, then it behaves as if the hint were
    Number, unless O is a Date object。

    ToPrimitive(with hint String) :
    1、 If IsCallable(toString) is true then,
    ----a . Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.
    ----b . If str is a primitive value, return str.
    2、If IsCallable(valueOf) is true then,
    ----a. Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and an empty argument list.
    ----b. If val is a primitive value, return val.
    3、 Throw a TypeError exception

    ToPrimitive(with hint Number) :
    1、If IsCallable(valueOf) is true then,
    ----a. Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and an empty argument list.
    ----b. If val is a primitive value, return val.
    2、 If IsCallable(toString) is true then,
    ----a . Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.
    ----b . If str is a primitive value, return str.
    3、 Throw a TypeError exception

    回复
    0
  • 迷茫

    迷茫2017-04-10 17:12:23

    对 + 操作符来说,计算顺序为从左往右
    如果2个操作数都是数字类型,那么结果也为数字
    如果2个操作数都是字符串,那么+操作符为字符串连接符,结果为字符串
    其它的请求下,+ 操作符偏好字符串连接操作
    如果其中一个操作数为对象,则对象会遵循对象到原始值的转换规则,转换为原始值,日期对象直接调用toString方法转成字符串,其它对象先调用valueOf方法,如果此方法返回一个原始值,那么次原始值作为操作数进行计算,如果没有valueOf方法或返回的不是一个原始值,那么调用toString方法转成字符串
    获得原始值后如果其中一个操作数为字符串,另一个操作数也要转成字符串,执行字符串连接操作
    否则转成数字执行加操作

    而 - 操作符必须要求2个操作数都为数字

    console.log(typeof (new Date()) + 1);
    typeof(new Date());返回 object字符串
    "object"+1;的结果为“object1”

    typeof (new Date())-1
    "object"+1;的结果为NaN 非数字

    console.log((new Date()) + 1);
    (new Date())返回字符串 Mon Feb 22 2016 14:48:26 GMT+0800 (CST)
    "Mon Feb 22 2016 14:48:26 GMT+0800 (CST)"+1结果为Mon Feb 22 2016 14:48:26 GMT+0800 (CST)1

    console.log((new Date()) - 1);
    -减法操作符 (new Date())输出执行valueOf方法,获取原始值-时间毫秒数

    回复
    0
  • PHPz

    PHPz2017-04-10 17:12:23

    问题一开始代码就写的错的。。。下面才是

    typeof (new Date() + 1)    //"string"
    typeof (new Date() - 1)    //"number"

    原因就很简单了,+号第一处被当成字符串拼接了。

    回复
    0
  • PHPz

    PHPz2017-04-10 17:12:23

    和操作符的优先级有关,typeof的优先级高于+,所以等价于,typeof操作后返回一字符串再+1拼接上1;最终呈现的的就是一个字符串"object1"

    回复
    0
  • 取消回复