Format Runtime Strings with ${name} Placeholders in JavaScript
· One min read
Native template literals work when variables are available directly in source code. When a template comes from configuration, an API, or a database, replace placeholders explicitly rather than evaluating the string as JavaScript.
function formatString(template, values) {
return template.replace(/\$\{([\w.-]+)\}/g, (placeholder, key) => {
return Object.prototype.hasOwnProperty.call(values, key)
? String(values[key])
: placeholder;
});
}
console.log(formatString("${name} is a cat", {name: "Tom"}));
console.log(formatString("${0} + ${1}", [10, 20]));
Do not use values[key] || placeholder, because valid values such as 0, false, and an empty string are falsy.
For nested paths:
function getByPath(object, path) {
return path.split(".").reduce(
(value, key) => value == null ? undefined : value[key],
object
);
}
function formatNested(template, values) {
return template.replace(/\$\{([\w.-]+)\}/g, (placeholder, path) => {
const value = getByPath(values, path);
return value === undefined ? placeholder : String(value);
});
}
Use native template literals for normal code:
const name = "Tom";
console.log(`Hello, ${name}`);
Never use eval or Function to process an untrusted template, because the template could execute arbitrary JavaScript.