Javascript字符串插值给出与字符串连接不同的结果

标签 javascript ecmascript-6 concatenation interpolation

我遇到了一个案例,其中 Javascript 字符串插值没有给出与字符串连接相同的结果。
这是显示差异的代码的简化版本:

const mmt = moment();
console.log('concatenated: ' + mmt); // "concatenated: 1651070909974"
console.log(`interpolated: ${mmt}`); // "interpolated: Wed Apr 27 2022 10:48:29 GMT-0400"
console.log('mmt.valueOf(): ' + mmt.valueOf()); // "mmt.valueOf(): 1651070909974"
console.log('mmt.toString(): ' + mmt.toString()); // "mmt.toString(): Wed Apr 27 2022 10:48:29 GMT-0400"
所以我的直接想法是,这是由于 .toString() 的差异造成的。和 .valueOf() ,所以我做了一个小测试对象来验证:
const obj = {
  toString: () => 'toString',
  valueOf: () => 'valueOf',
};

console.log('concatenated: ' + obj); // "concatenated: valueOf"
console.log(`interpolated: ${obj}`); // "interpolated: toString"
console.log('obj.valueOf(): ' + obj.valueOf()); // "obj.valueOf(): valueOf"
console.log('obj.toString(): ' + obj.toString()); // "obj.toString(): toString"
但是,当我使用 Date 对象(与 .toString().valueOf() 的结果也不同)尝试此操作时,我没有得到相同的行为——这次插值和连接都使用 .toString()值(value):
const dte = new Date();
console.log('concatenated: ' + dte); // "concatenated: Wed Apr 27 2022 10:48:29 GMT-0400 (Eastern Daylight Time)"
console.log(`interpolated: ${dte}`); // "interpolated: Wed Apr 27 2022 10:48:29 GMT-0400 (Eastern Daylight Time)"
console.log('dte.valueOf(): ' + dte.valueOf()); // "dte.valueOf(): 1651070909974"
console.log('dte.toString(): ' + dte.toString()); // "dte.toString(): Wed Apr 27 2022 10:48:29 GMT-0400 (Eastern Daylight Time)"
所以我的问题是:在连接和插值时如何将插值转换为字符串的实际规则是什么,为什么 Date 似乎与其他对象不同? (我试图查找这个,但到目前为止我的谷歌搜索一直不成功......)
JSFiddle Example

最佳答案

行为上的差异确实与 + 相关。运算符,它背后有一个特定的过程:
关于抽象操作的 ECMAScript 规范 ToPrimitive指定如果没有提供类型提示(如 the + operator 的情况),将发生以下情况:

  • 如果对象有 Symbol.toPrimitive方法,然后它将被调用(提示“默认”)。此方法可以将调用转发到 toString . Date 就是这种情况。对象。
  • 如果对象没有这样的方法,“数字”是默认值,valueOf将被调用。 moment 就是这种情况。目的。

  • 处理 + 过程复杂的原因运算符,是它还用于算术加法。
    这种复杂性在评估模板文字时不存在,因为总是要进行字符串连接,因此 Symbol.toPrimitive方法将使用“字符串”提示(而不是“默认”)调用,或者如果该方法不存在,toString将被调用。
    所以你的假设 +是纯字符串连接,不是那么准确。当您使用 .concat 时,看看它的不同之处。方法:

    const mmt = moment();
    console.log('concatenated: '.concat(mmt));
    // Not same result as with +
    console.log('plus operator: ' + mmt);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.3/moment.min.js"></script>

    关于Javascript字符串插值给出与字符串连接不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72031214/

    相关文章:

    javascript - Firefox selectedIndex on select 在悬停时更改

    javascript - 将数字转换为 Unicode 符号

    javascript - Action 调度后无法获取新 Prop

    sql - 无冗余获取SQL Server的约束列表

    python - 如何在 Python 中制作相同大小的数组

    javascript - Bootstrap 可切换选项卡无法正常工作

    javascript - 如何仅为非字母字符验证字符串 jquery validation

    javascript - 使用循环变量进行同名函数调用 - Javascript

    javascript - Promise returns in a chain 的误解

    Mysql - "Order by"无法使用 "CONCAT"工作