JavaScript 模板文字保证调用 toString() 吗?

Are JavaScript template literals guaranteed to call toString()?

const num = 42
const str = `My number is ${num}`

在这段代码中,我对 numstring 的转换有什么保证?

是否保证只调用它的 toString() 方法,或者可以通过其他方式完成转换?

是的。如果任一值不是字符串,它将使用通常的规则转换为字符串。例如,如果 action 是一个对象,它的 .toString() 方法将被调用。

阅读来自 mozilla 的完整文章 https://hacks.mozilla.org/2015/05/es6-in-depth-template-strings-2/

是的,它是 Object 原语的函数,如 MDN

中所述

编辑: ECMA 规范是 expression,如 here 所述。

又在MDN - Template literal写成:

默认函数只是将各个部分连接成一个字符串

无标记模板使用 ECMAScript ToString() 抽象操作。模板文字评估的逻辑分布在几个部分,这使得它很难理解,所以我只是 post 一个 link 到它:https://tc39.es/ecma262/#sec-template-literals-runtime-semantics-evaluation

ToString(argument) 使用 table 而不是算法步骤,所以我会在这里写一些伪代码:

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) 将尝试从 input 获取 Symbol.toPrimitive 方法,如果存在,则使用给定的 PreferredType 提示调用它。如果 input 没有 Symbol.toPrimitive 属性,它会退回到 OrdinaryToPrimitive.

OrdinrayToPrimitive(O, hint) 将尝试调用 toStringvalueOf 方法。如果hint'string',它会先尝试调用toString方法,否则会先尝试调用valueOf方法。如果存在这些方法中的任何一个并且它们不是 return 对象,则将使用它们的 return 值。如果两者都不存在或它们都是 return 个对象,则会抛出 TypeError。

所以要回答你原来的问题,转换 42 不会调用任何其他方法。引擎将在内部创建一个字符串表示形式 ('42'),并使用它。