【问题标题】:JS valueOf and toStringJS valueOf 和 toString
【发布时间】:2015-03-23 18:32:39
【问题描述】:

x 中发生了哪些在y 中没有发生的魔法?

var x = new Date;
var y = {
    toString: function() {
        return x.toString();
    },
    valueOf: function() {
        return x.valueOf();
    }
};

String(x) // "Mon Mar 23 2015 18:26:40 GMT+0000 (GMT)"
String(y) // "Mon Mar 23 2015 18:26:40 GMT+0000 (GMT)"
'' + x    // "Mon Mar 23 2015 18:26:40 GMT+0000 (GMT)"
'' + y    // "1427135200422"

我是否认为x 具有将ToStrings 作为日期字符串的原始值,但y 没有原始值?

编辑:

对于它的价值,以下工作是否可行(此处为 ES6):

var y = {
    [Symbol.toPrimitive](...args) {
        return x[Symbol.toPrimitive](...args);
    }
};

【问题讨论】:

    标签: javascript tostring


    【解决方案1】:

    来自规范的第 8.12.8 节:

    当 O 的 [[DefaultValue]] 内部方法在没有提示的情况下被调用时,它的行为就像提示是数字一样,除非 O 是一个 Date 对象(参见 15.9.6),在这种情况下它的行为就像提示是字符串。

    + 运算符传递了“PreferredType”提示,它的行为就像没有提示一样(尽管规范没有很好地解释,或者我找不到它)。因此,您的 x 对象“更喜欢”它的字符串表示,而 y 对象使用数字表示。

    【讨论】:

    • 它仅在加法运算符步骤之后的“注 1”中明确表示:“在步骤 5 和 6 中对 ToPrimitive 的调用中未提供提示。”
    • 很奇怪。 0 + x 给出一个字符串,0 - x 给出一个数字。
    • @apsillers 啊,好的;我按照[[ToPrimitive]] 部分中的图表进行。
    • @user2195592 这是因为+ 运算符和- 运算符具有不同的行为。 + 运算符兼作字符串连接运算符,而 - 运算符始终是数字减法。
    【解决方案2】:

    + 的行为定义在

    11.6.1 The Addition operator ( + )

    产生式 AdditiveExpression : AdditiveExpression + MultiplicativeExpression 计算如下:

    1. lref 为 AdditiveExpression 的计算结果。
    2. lvalGetValue(lref)。
    3. rref 为 MultiplicativeExpression 的计算结果。
    4. rvalGetValue(rref)。
    5. lprimToPrimitive(lval)。
    6. rprimToPrimitive(rval)。
    7. 如果Type(lprim) 是字符串或Type(rprim) 是字符串,那么
      1. 返回字符串,它是连接ToString(lprim) 后跟ToString(rprim)的结果
    8. 返回对ToNumber(lprim) 和ToNumber(rprim) 应用加法运算的结果。请参阅下面的注释11.6.3

    注意 1 - 在步骤 5 中对 ToPrimitive 的调用中未提供任何提示 6. 除 Date 对象外的所有原生 ECMAScript 对象都处理 没有提示,好像给出了提示编号;日期对象 处理没有提示的情况,就好像给出了提示字符串一样。主持人 对象可能会以其他方式处理提示的缺失。

    因此,根据ToPrimitive[[DefaultValue]]的定义,

    • ToPrimitive 为 x 返回 x.toString(),因为 x 是一个 Date 对象,所以它就像提示是 String。

    • ToPrimitive 为 y 返回 y.valueOf(),因为 y 是一个非 Date 原生对象,所以它就像提示是 Number。

    因此,加法运算符返回不同的结果。

    【讨论】:

    • 等等,为什么是x.toString()
    • @user2195592 因为x 是一个 Date 实例,这就是规范在NOTE 1 中所说的内容。
    • 我现在明白了。谢谢!
    猜你喜欢
    • 2019-01-09
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多