【问题标题】:How do ES6 tagged template functions interpret their argument order?ES6 标记的​​模板函数如何解释它们的参数顺序?
【发布时间】:2014-09-09 02:32:51
【问题描述】:

考虑以下代码:

function f() {
  console.log(Array.from(arguments));
}

var x = 2;
var y = 3;
f`before ${x} ${y} after`;

f 的参数将是 (according to Traceur):

["before ", " ", " after"], 2, 3

假设我想用替换值连接所有文字字符串。
如何以正确的顺序执行此操作?

我是否需要将第一个数组中的“分割点”与 first 之后的每个参数进行匹配?

【问题讨论】:

  • 看起来像。如果您查看 AST,模板字符串被“划分”为三个 quasis 和两个表达式(至少 esprima 是这样做的)。谦虚的自我推销:felix-kling.de/esprima_ast_explorer 让您检查 AST。
  • default quasi tag 不就是这样吗?

标签: javascript ecmascript-6 template-strings


【解决方案1】:

根据 ECMAScript 6 规范草案的 wiki,它更复杂,因为模板考虑了转义序列:

模板

quasiTag`literalPortion\0 $x literalPortion1`

会脱糖到

// Declaration hoisted to top of module.
// Escape sequences in the hoisted declaration are not decoded according to CV(EscapeSequence).
// The calls to Object.freeze use the original definition of that method.
const unguessableCallSiteId1234 = Object.freeze({
  raw: Object.freeze(["literalPortion\\0 ", "literalPortion1"]),
  cooked: Object.freeze(["literalPortion\u0000 ", "literalPortion1"])
});

...

  // In-situ
  // Escape sequences in the arguments are decoded.
  // unguessableCallSiteId1234 is ideal as a key into a weak map used to memoize
  // extraction of meta-data, custom escaping conventions, and other state
  // that can be derived from the literal portions, so does not vary from
  // call to call from the same call-site.
  quasiTag(unguessableCallSiteId1234, x)

EcmaScript Quasi-Literals - Desugaring

所以arguments 应该包含您在 traceur 中看到的替换值,但文字部分是对象而不是数组。

如果您想为使用 traceur 编译的代码实现它,您可以执行以下未优化示例中的操作。

let concatenated = "";
Array.forEach(args[0], (e, i) =>
    concatenated += e + ( i < arguments.length - 1 ? arguments[i+1] : "")
);

对于真正的 ECMAScript 6 代码,请查看 Default Quasi Tag 实现,正如 bergi 在 cmets 中建议的那样。

【讨论】:

  • 谢谢!那是最新版本吗?目前我看到三个版本:1)草案规范定义(对象raw/cooked),2)草案规范默认准标签(使用一些名为expandedLP的属性)和3)跟踪器实现('cooked'数组raw 作为属性)。生/熟对象 (1) 是最后一个吗?
  • @AndreyShchekin 我能找到的最新草稿来自 2014-07-18 wiki.ecmascript.org/doku.php?id=harmony:specification_drafts。在 12.2.9 Template Literals 中,他们使用 raw/cooked object (1) 变体。看起来他们已经删除了名称 quasi literals 并将整个内容重命名为 template literals。它仍然是一个草稿,所以没有人能确定它是否会是最终版本。
【解决方案2】:

总是比替换多一个字面部分。第一个文字是模板的第一部分(如果以替换开头,则为空字符串),最后一个文字是模板字符串的尾部(或者,如果以替换结尾,则为空字符串)。

要按顺序获取零件,请访问literal[0]sub[0]literal[1]、...、sub[sub.length-1]literal[sub.length]

这是一个简单的起点:

function simpleTag(lit, ...sub) {
  return sub.reduce(
    // Add next substition and following literal
    (soFar, s, i) => soFar + s + lit[i+1],
    lit[0] // Start with the first literal
  );
}

【讨论】:

    猜你喜欢
    • 2013-04-01
    • 1970-01-01
    • 2014-10-08
    • 2018-02-23
    • 2016-11-20
    • 2018-10-23
    • 2016-11-07
    相关资源
    最近更新 更多