Kip*_*Kip 6 javascript interpolation concatenation ecmascript-6
我遇到过一种情况,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"
Run Code Online (Sandbox Code Playgroud)
所以我的第一反应是,这是由于.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"
Run Code Online (Sandbox Code Playgroud)
但是,当我使用 Date 对象(它也有与.toString()vs不同的结果.valueOf())尝试此操作时,我没有得到相同的行为 - 这次插值和连接都使用该.toString()值:
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)"
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:连接与插值时插值如何转换为字符串的实际规则是什么,以及为什么 Date 似乎与其他对象不同?(我试图查找这一点,但到目前为止我的谷歌搜索尚未成功......)
行为的差异确实与操作符有关+,操作符背后有一个特定的过程:
关于抽象操作ToPrimitive的 ECMAScript 规范指定,如果未提供类型提示(如操作符的情况)+,则会发生以下情况:
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);Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.3/moment.min.js"></script>Run Code Online (Sandbox Code Playgroud)