JavaScript 字符串模板替换:实现 ${name} 占位符与嵌套路径
· 阅读需 2 分钟
JavaScript 模板字符串适合在代码中直接插入变量,但如果模板来自配置文件、接口或数据库,就需要在运行时根据对象替换 ${name} 形式的占位符。
基础实现
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]));
正则表达式中的捕获组会直接取得占位符名称,不需要再手动调用 substring 去掉 ${ 和 }。
正确处理 0、false 和空字符串
不能用下面的写法判断变量是否存在:
const replacement = values[key] || placeholder;
因为 0、false 和空字符串都会被当成假值。使用 hasOwnProperty 可以区分“属性不存在”和“属性存在但值为空”:
const template = "count=${count}, enabled=${enabled}, text=${text}";
console.log(formatString(template, {
count: 0,
enabled: false,
text: ""
}));
// count=0, enabled=false, text=
支持点号路径
如果模板需要读取嵌套对象,可以增加路径解析:
function getByPath(object, path) {
return path.split(".").reduce((value, key) => {
return 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);
});
}
const user = {
profile: {
name: "Tom"
}
};
console.log(formatNested("Hello, ${profile.name}", user));
与原生模板字符串的区别
代码中的变量推荐使用原生模板字符串:
const name = "Tom";
console.log(`Hello, ${name}`);
自定义 formatString 适用于模板是普通字符串的场景。不要使用 eval 或动态构造函数解析外部模板,否则不可信内容可能执行任意 JavaScript 代码。