How do ES6 tagged template functions interpret their argument order?

独自空忆成欢 提交于 2019-12-24 04:14:09

问题


Consider the following code:

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

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

The arguments for f would be (according to Traceur):

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

Let's say I want to concatenate all literal strings with substitution values.
How do I do that in the correct order?

Do I need to match 'split points' in the first array with each argument after first?


回答1:


According to the wiki for the Draft ECMAScript 6 Specification, it is more complicated because templates take escape sequences into account:

The template

quasiTag`literalPortion\0 $x literalPortion1`

will desugar to

// 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

So arguments should contain the substitution values as you see with traceur but the literal portions are an object and not an array.

If you want to implement it for code compiled with traceur you could do something like in the following unoptimized example.

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

For real ECMAScript 6 code take a look at the Default Quasi Tag implementation, as bergi suggested in the comments.




回答2:


There's always one more literal portion than substitution. The first literal is the first part of the template (or empty string if it starts with a substitution), and the last literal is the tail of the template string (or, again, an empty string if it ends with a substitution).

To get the parts in order, access literal[0], sub[0], literal[1], ..., sub[sub.length-1], literal[sub.length].

Here's a simple starting point:

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
  );
}


来源:https://stackoverflow.com/questions/24816777/how-do-es6-tagged-template-functions-interpret-their-argument-order

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!