5 ms·
The most interesting part about template strings was skipped over: tagged template literals. You can prefix a template string with a function which will get cal
by AgentME 10y ago
The most interesting part about template strings was skipped over: tagged template literals. You can prefix a template string with a function which will get called with the list of string parts and the values passed in ${...} parts, and then it's up to the function to choose how to join the values up into the resulting string (or hell, you could make it return something besides a string if you want). The function can even access the raw version of the string containing any backslash escapes in it as-is. The default `String.raw` function is handy if you're writing something like an SQL query with a few \ characters that need to be in the final query. Both of these strings are the same here:
const a = "SELECT id FROM foo WHERE name CONTAINS r'\\n'";
const b = String.raw `SELECT id FROM foo WHERE name CONTAINS r'\n'`;
You could even assign `String.raw` to a variable first, and then make strings look like raw string literals of other languages:
const r = String.raw;
const s = r`SELECT id FROM foo WHERE name CONTAINS r'\n'`;
Another good use of template strings is automatic HTML encoding (with a small module of mine on npm): https://www.npmjs.com/package/auto-html https://www.npmjs.com/package/auto-html
- CGamesPlay 10y agoHow does this work? I can't find any examples and I also don't really understand what mechanism makes your npm module work.
- AgentME 10y agoA tagged template literal is just a special ES6 syntax for calling a function with a specific set of arguments. You could pass a function which returns all of the arguments as an array to see what's passed in. Try the following in the console of a modern browser: function log(...args) { return args; } log `abc ${'blah'} fooo\n ${12+3} bar`; Or you could even shorten the above down to this: ((...args)=>args) `abc ${'blah'} fooo\n ${12+3} bar`; The expression will evaluate to this: [["abc ", " fooo\n ", " bar"], "blah", 15] The first argument is an array of the parts of the literal text, and then the rest of the arguments are the values that were passed in. Additionally, the first argument (the array of string parts) has the `raw` property set to point to an array of string parts with the backslash escapes uninterpreted. Here's an example re-implementation of `String.raw`: function raw({raw}, ...values) { const parts = new Array(raw.length*2-1); parts[0] = raw[0]; for (let i=0, len=values.length; i<len; i++) { parts[2*i+1] = values[i]; parts[2*i+2] = raw[i+1]; } return parts.join(''); }
- adriansky 10y agoTagged templates look interesting. It's an overlooked feature that not many people know about
- deleted 10y ago[deleted]
- pluma 10y agoSQL actually demonstrates a good use case for custom template handlers. It's not SQL, but we're using a template handler to make writing parameterized queries trivial for ArangoDB: https://github.com/arangodb/arangojs#aql https://github.com/arangodb/arangojs#aql Example: var userCollection = db.collection('_users'); var role = 'admin'; db.query(aql` FOR user IN ${userCollection} FILTER user.role == ${role} RETURN user `) The template handler returns an object with the parameterized query string and the parameter values, which the `query` method understands. Because collection parameters are syntactically distinct from regular parameters this also avoids accidentally passing in arbitrary strings as collection names -- and of course it completely avoids injection attacks as a category. In my experience this is actually much more comfortable to use than a "fluent" API that tries to map the query language to the programming language (i.e. `select('id').from('foo')` and so on). Full disclosure: I wrote that library.