如何优雅地在字符串模板中访问JavaScript对象属性?
优雅实现JavaScript对象数据到模板字符串的映射
问题场景
现有存储数据的JS对象,以及带有%属性路径%格式占位符的模板字符串,需要将对象中的数据动态填充到模板对应位置。原始方案手动提取变量、构建映射后替换,不仅繁琐还容易出错,希望找到类似模板字面量、能直接用JS语法访问对象属性的优雅实现。
示例数据与模板:
const menu = { breakfast: { description: 'something' }, meal: { description: 'anotherSomething' } }; const template = `<div> <ul> <li> %breakfast.description% </li> <li> %meal.description% </li> </ul> </div>`;
方案1:正则匹配 + 递归解析属性路径
无需依赖eval,安全可靠,完美支持嵌套属性访问:
// 解析嵌套属性的工具函数 function getNestedValue(obj, path) { return path.split('.').reduce((current, key) => { // 路径不存在时返回空字符串避免报错 return current?.[key] ?? ''; }, obj); } // 模板渲染函数 function renderTemplate(template, data) { // 匹配所有%xxx.xxx%格式的占位符 return template.replace(/%([\w.]+)%/g, (_, path) => { return getNestedValue(data, path); }); } // 使用示例 const renderedHtml = renderTemplate(template, menu); console.log(renderedHtml);
方案2:利用Function构造函数模拟模板字面量
这种方式完全贴近模板字面量的使用体验,还支持更复杂的JS表达式:
function renderTemplate(template, data) { // 将%xxx%占位符替换为模板字面量的${data.xxx}格式 const literalStr = template.replace(/%([\w.]+)%/g, '${data.$1}'); // 通过Function构造函数动态执行模板字符串 return new Function('data', `return \`${literalStr}\``)(data); } // 使用示例 const renderedHtml = renderTemplate(template, menu); console.log(renderedHtml);
方案对比
- 方案1:安全性高,适合处理不可信来源的模板,但仅支持属性路径访问,无法处理复杂表达式;
- 方案2:灵活性强,支持任意合法JS表达式,但如果模板来源不可信,存在代码注入风险,仅适用于可信模板场景;
- 原始方案的缺陷:手动维护变量数组容易遗漏,且
replace方法不会修改原字符串(JS字符串是不可变的),循环中的替换操作实际不会生效,需要将替换结果重新赋值才能保存修改。
内容的提问来源于stack exchange,提问作者Manuel Duarte
相关产品推荐
相关产品推荐

