本文介绍一种基于 Function 构造函数的安全模板变量替换方案,支持嵌套对象访问、默认值回退(||)、字符串字面量及 XSS 防护,避免 eval 风险并内置缓存优化。
本文介绍一种基于 `function` 构造函数的安全模板变量替换方案,支持嵌套对象访问、默认值回退(`||`)、字符串字面量及 xss 防护,避免 `eval` 风险并内置缓存优化。
在前端开发中,常需将 JavaScript 对象中的值动态注入 HTML 模板字符串(如 {{user.name}} 或 {{config.url || "/default"}})。但直接使用正则 + eval 存在严重安全隐患(作用域污染、XSS 注入、调试困难),而手动解析表达式又过于繁琐。推荐采用
new Function() + 作用域隔离 + HTML 转义
的组合方案,兼顾安全性、灵活性与性能。
以下是经过生产级优化的核心实现:
使用示例:
注意事项与最佳实践:
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
立即学习
“
Java免费学习笔记(深入)
”;
作用域必须显式传入
:不能依赖闭包或全局变量,所有变量需在调用时以 {key: value} 形式提供(如 {uu, works}),确保表达式可预测、可审计;
禁用未转义 HTML 插入
:默认对所有插值结果执行 escape(),若需渲染可信 HTML,请扩展语法(例如 {{!unsafe.
html
}})并单独处理;
错误防御
:try...catch 包裹表达式执行,避免单个模板错误导致整个渲染失败;
性能优化
:利用 cache 参数复用已编译的 Function 实例,相同表达式仅解析一次;
不支持 this / 箭头函数 / 模块语法
:new Function() 仅支持纯表达式(如 uu.name、items[0].id || "N/A"),不支持语句块或新特性;
该方案已在轻量级模板引擎和配置化 UI 渲染场景中验证,平衡了安全性、可维护性与运行效率,是替代 eval 的可靠选择。
// 安全的 HTML 转义函数(防止 XSS)
const escape = (str) => {
if (str == null) return '';
const span = document.createElement('span');
span.textContent = str;
return span.innerHTML;
};
// 主替换函数:支持嵌套属性、逻辑或回退、缓存加速
const insertReplacements = (htmlStr, scope, cache = {}) => {
// 将 scope 对象键名构造成形参列表,如 {uu, works} → 'uu,works'
const argNames = Object.keys(scope).join(',');
const args = `{${argNames}}`;
return htmlStr.replace(/\{\{(.*?)\}\}/g, (_, expr) => {
// 缓存已编译的表达式函数,避免重复解析
const fn = cache[expr] ??= new Function(args, `return ${expr}`);
try {
// 在严格限定的作用域内执行表达式
const value = fn(scope);
// 默认对所有输出进行 HTML 转义(若需原生 HTML,请额外标记,如 {{!raw.html}})
return escape(value);
} catch (e) {
console.warn(`Template expression failed: "{{${expr}}}", error:`, e);
return '';
}
});
};const works = "It_works";
const uu = {
message: 'use this message here. ',
learnMore: 'learn more',
link: 'dai sit ein link',
target: '_self',
markup: '{{uu.message}} test: {{works}} {{uu.learnMore}}'
};
// ✅ 关键:传入扁平化作用域对象 {uu, works}
const result = insertReplacements(uu.markup, { uu, works });
console.log(result);
// 输出:
// "use this message here. test: It_works learn more" 