跳到主要内容

JavaScript 字符串模板替换:实现 ${name} 占位符与嵌套路径

· 阅读需 2 分钟
Apache王也道长
软件开发者与技术作者

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;

因为 0false 和空字符串都会被当成假值。使用 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 代码。

本文阅读量:--

总访问量 -- · 访客数 --