JavaScript字符串插值与字符串串联给出了不同的结果
我遇到了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()
and 和.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"
但是,当我尝试使用一个日期对象尝试此对象时(与.toString()
vs .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)"
,所以我的问题是:在串联与插值时,插值值如何转换为字符串的实际规则是什么?为什么日期似乎与其他对象有所不同? (我已经尝试查找此问题,但是到目前为止,我的谷歌搜索没有成功...)
I ran across a case where Javascript string interpolation is not giving the same result as string concatenation.
Here is a simplified version of the code showing the difference:
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"
So my immediate thought was that it was due to a difference in .toString()
and .valueOf()
, so I made a small test object to verify:
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"
However, when I tried this with a Date object (which also has a different result from .toString()
vs .valueOf()
), I do not get the same behavior--this time interpolation and concatenation both use the .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)"
So my questions is: What are the actual rules for how an interpolated value is converted to a string when concatenated vs interpolated, and why does Date seem to be different from other objects? (I have tried to look this up, but thus far my googling has been unsuccessful...)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
行为的差异确实与
+
运算符有关,该操作员背后有一个特定的过程:摘要操作上的ecmascript规范 toprivitive 指定如果没有提供类型提示(如
+
操作员)发生以下情况:symbor.tprimitive
方法,那么它将称为(带有提示“默认”)。此方法可以将调用转发到toString
。date
对象就是这种情况。MONM
对象就是这种情况。处理
+
运算符时,此复杂过程的原因是,它也用于算术添加。在评估模板文字中不存在这种复杂性,其中始终是字符串串联的意图,因此
符号。toprimitive
方法将用“字符串”提示调用(而不是“默认”),或者如果不存在该方法,则会调用tostring
。因此,您假设
+
是纯字符串串联,不是那么准确。当您使用.concat
方法:The difference in behaviour is really related to the
+
operator, which has a specific procedure behind it:The ECMAScript specification on the abstract operation ToPrimitive specifies that if no type hint is provided (as is the case with the
+
operator) the following happens:Symbol.toPrimitive
method, then it will be called (with hint "default"). This method may forward the call totoString
. This is the case withDate
objects.valueOf
will be called. This is the case with themoment
object.The reason for this complex procedure in handling the
+
operator, is that it also serves for the arithmetic addition.This complexity is not present in evaluating template literals, where always string concatenation is intended, and so the
Symbol.toPrimitive
method will be called with the "string" hint (instead of "default"), or if that method does not exist,toString
will be called.So your assumption that
+
is a pure string concatenation, is not that accurate. See how it is also different when you use the.concat
method: