const num = 42
const str = `My number is ${num}`
在这段代码中,我对
num
到 string
的转换有何保证?
是否保证只调用它的
toString()
方法或者可以通过其他方式完成转换?
未标记模板使用 ECMAScript
ToString()
抽象操作。模板文字评估的逻辑分布在几个部分,这使得它很难理解,所以我只发布一个链接:https://tc39.es/ecma262/#sec-template-literals-runtime-semantics -评价
ToString(argument)
使用表格而不是算法步骤,所以我将在这里写出一些伪代码:
switch (Type(argument)) {
case 'Undefined':
return 'undefined';
case 'Null':
return 'null';
case 'Boolean':
return argument ? 'true' : 'false';
case 'Number':
return Number::toString(argument);
case 'String':
return argument;
case 'Symbol':
throw new TypeError();
case 'BigInt':
return BigInt::toString(arugment);
case 'Object':
return ToString(ToPrimitive(argument, 'string'));
}
如您所见,对于原始值根本不会执行任何 js,引擎内部会创建一个字符串表示形式。对于对象,我们进入
ToPrimitive()
算法。
ToPrimitive(input, PreferredType)
将尝试从 Symbol.toPrimitive
获取 input
方法,如果存在,则使用给定的 PreferredType
提示调用它。如果 input
没有 Symbol.toPrimitive
属性,则它会回落到 OrdinaryToPrimitive
。
OrdinrayToPrimitive(O, hint)
将尝试调用 toString
和 valueOf
方法。如果 hint
是 'string'
,则首先尝试调用 toString
方法,否则将尝试先调用 valueOf
方法。如果这些方法中的任何一个存在并且它们不返回对象,则将使用它们的返回值。如果两者都不存在或者都返回对象,则会抛出 TypeError。
因此,为了回答您原来的问题,转换
42
不会调用任何其他方法。引擎将在内部创建一个字符串表示形式 ('42'
),并使用它。
是的。如果其中一个值不是字符串,则会使用通常的规则将其转换为字符串。例如,如果action是一个对象,它的.toString()方法将被调用。
阅读 mozilla 的全文 https://hacks.mozilla.org/2015/05/es6-in-deep-template-strings-2/
toString
在 JavaScript 模板文本中不被调用
let p = 123;
let c = p.constructor;
if (typeof c.prototype.toString2 !== 'function') {
c.prototype.toString2 = c.prototype.toString;
c.prototype.toString = function () {
console.log("toString is called")
return this.toString2();
}
}
console.log("Test 1");
console.log(p + "")
console.log("Test 2");
console.log(p.toString())
console.log("Test 3");
console.log(`${p}`)
console.log("Test 4");
typeof p === 'number' && console.log(p.toFixed())