【问题标题】:How to call native es6 template string replacement from tag function?如何从标记函数调用本机 es6 模板字符串替换?
【发布时间】:2016-11-07 15:45:06
【问题描述】:

我正在为模板文字编写一个 es6 标记函数,它首先检查字符串中的条件,如果未找到条件,则仅将模板文字解释为没有标记。我很好奇,是否有一种方法可以从我的标记函数中调用浏览器的本机模板文字函数(我认为它会比 我自己实现的函数 更快)。 Bonue:这样就不能有标签合成的机会,比如htmlEscape(unndentfoobar);

例如。

function dumbTag(strs, ...vals) {
    vals = vals.map((val,i) =>
            (i % 2 == 0 ? 'even:' : 'odd:')+val);
    return String.template(strs, ...vals);
}

我自己实现的功能 - 有没有更快的方式/方式来调用浏览器的功能?

function template(strs, ...vals) {
    let result = strs[0];
    for (let [i,val] of vals.entries()) {
        result += val;
        result += strs[i+1];
    }
    return result;
}

【问题讨论】:

  • 我认为没有可以调用的函数...如果你找到了,请告诉我。
  • 什么是substs,你的意思是vals
  • @Bergi 是的,已更新

标签: javascript ecmascript-6 variadic-templates template-literals


【解决方案1】:

没有这样的内置函数 - 未标记的模板文字只是直接评估为字符串。

有没有更快的方法?

这在很大程度上取决于实施。如果您使用的是转译器,我会避免使用其余参数、迭代器和for of 循环:

function template(strs) {
    var result = strs[0];
    for (var i=1; i < strs.length; i++) {
        result += arguments[i];
        result += strs[i];
    }
    return result;
}

【讨论】:

    【解决方案2】:

    你可以(ab)使用String.raw(唯一的内置标签)来达到这个目的:

    function doNothingTag() {
      arguments[0] = { raw: arguments[0] };
      return String.raw(...arguments);
    }
    
    // Or in a more modern style:
    const doNothingTag = (strings, ...rest) => String.raw({ raw: strings }, ...rest);
    
    doNothingTag`It works!`
    // "It works!"
    
    doNothingTag`Even\nwith\nescape\nsequences!`
    // "Even
    // with
    // escape
    // sequences!"
    

    这本质上只是在欺骗String.raw 认为转义解释的字符串是原始版本。

    【讨论】:

    • 所以,只要您确定您的模板中没有任何转义序列,您就可以使用String.raw“原样”,即const tag = String.raw;
    【解决方案3】:

    可以通过使用Array.prototype.flatMap() 来完成一个简短的实现,如下所示:

    const defaultTag = (strs, ...vals) =>
      strs.flatMap((x, i) => [x, i < vals.length ? vals[i] : undefined]).join('');
    
    const name = 'Some name';
    const age = 32;
    
    console.log(defaultTag`Hi my name is ${name}, and I'm ${age} years old!`);

    【讨论】:

    • 这将访问vals 上的越界索引。 .join() 会忽略生成的 undefined 值,但您仍然不应该这样做。
    • 我为什么不应该呢?这种行为在浏览器中是一致的,所以它不应该容易出错。
    • 我并不是说它不起作用,我是说这是一种不好的做法并且会阻止编译器优化。
    • 编译器是否知道我将在运行时访问越界项?
    • Yes.
    【解决方案4】:

    我也想知道是否有这样的原生功能。与此同时,这是我使用的:

    const tag = ([head, ...tail], ...args) => tail.reduce((a, b, i) => a + args[i] + b, head);
    

    【讨论】:

    • const tag = (strings, ...values) =&gt; values.reduce( (s, v, i, strings) =&gt; `${s}${v}${strings[i + 1]}`, strings[0] ); // A slightly shorter version
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-19
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多