I'm writing a es6 tag function for template literals, which first checks a condition in the string and, if the condition isn't found, merely interprets the template literal as if it were untagged. I am curious if, from my tag function, there is a way to call the browser's native template literal function (which I assume would be faster than my own implemented function). Bonue: With this, couldn't there be an opportunity for tag position, eg htmlEscape(unindentfoobar
);
eg.
function dumbTag(strs, ...vals) {
vals = vals.map((val,i) =>
(i % 2 == 0 ? 'even:' : 'odd:')+val);
return String.template(strs, ...vals);
}
my own implemented function - is there a faster way / way to call what the browser does?
function template(strs, ...vals) {
let result = strs[0];
for (let [i,val] of vals.entries()) {
result += val;
result += strs[i+1];
}
return result;
}
I'm writing a es6 tag function for template literals, which first checks a condition in the string and, if the condition isn't found, merely interprets the template literal as if it were untagged. I am curious if, from my tag function, there is a way to call the browser's native template literal function (which I assume would be faster than my own implemented function). Bonue: With this, couldn't there be an opportunity for tag position, eg htmlEscape(unindentfoobar
);
eg.
function dumbTag(strs, ...vals) {
vals = vals.map((val,i) =>
(i % 2 == 0 ? 'even:' : 'odd:')+val);
return String.template(strs, ...vals);
}
my own implemented function - is there a faster way / way to call what the browser does?
function template(strs, ...vals) {
let result = strs[0];
for (let [i,val] of vals.entries()) {
result += val;
result += strs[i+1];
}
return result;
}
Share
Improve this question
edited Jul 5, 2016 at 23:53
Aaron_H
asked Jul 5, 2016 at 17:49
Aaron_HAaron_H
1,6831 gold badge13 silver badges26 bronze badges
3
- I don't think there is a function to call... if you find one, let me know. – ssube Commented Jul 5, 2016 at 18:06
-
What's
substs
, did you meanvals
? – Bergi Commented Jul 5, 2016 at 18:54 - @Bergi Yes, updated – Aaron_H Commented Jul 5, 2016 at 23:54
4 Answers
Reset to default 14You can (ab)use String.raw
(currently the only built-in tag) for this purpose:
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!"
This is essentially just tricking String.raw
into thinking that the escape-interpreted string is the raw version.
March 2024 update:
There is a proposal (currently at stage 1 in the process) for a "String.cooked
" function to solve this more elegantly.
There is no such builtin function - untagged template literals are just evaluated straight to strings.
is there a faster way?
That depends a lot on the implementation. In case you are using a transpiler, I would avoid using rest parameters, iterators and for of
loops:
function template(strs) {
var result = strs[0];
for (var i=1; i < strs.length; i++) {
result += arguments[i];
result += strs[i];
}
return result;
}
I was also wondering if there is such a native function. In the meantime, this is what I use:
const tag = ([head, ...tail], ...args) => tail.reduce((a, b, i) => a + args[i] + b, head);
A short implementation could be done by using Array.prototype.flatMap()
like this:
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!`);