本文介绍一种使用 new Function() 安全执行模板表达式、结合作用域对象动态替换 {{...}} 占位符的专业方案,支持链式属性访问、默认值语法(||)及 XSS 自动转义,兼顾性能与安全性。
本文介绍一种使用 `new function()` 安全执行模板表达式、结合作用域对象动态替换 `{{...}}` 占位符的专业方案,支持链式属性访问、默认值语法(`||`)及 xss 自动转义,兼顾性能与安全性。
在前端模板渲染场景中,常需将形如 {{uu.message}} 或 {{uu.link || "#null"}} 的占位符,依据传入的作用域对象(如 {uu, works})实时求值并替换为对应内容。直接使用 eval 存在严重安全隐患(变量污染、作用域泄露、XSS 风险),而手动解析表达式又过于复杂。推荐采用 new Function() 构造函数 + 严格作用域隔离 + 自动 HTML 转义 的组合方案。
// 安全转义函数:将任意字符串转为 HTML 安全文本(不执行标签)const escape = (str) => { if (str == null) return ''; const span = document.createElement('span'); span.textContent = str; return span.innerHTML;};// 主替换函数const insertReplacements = (htmlStr, scope, cache = {}) => htmlStr.replace(/{{(.*?)}}/g, (_, expr) => { try { // 构造参数列表:{key1,key2,...},确保作用域隔离 const args = '{' + Object.keys(scope).join(',') + '}'; // 编译并执行表达式,自动缓存编译后的函数 const fn = cache[expr] ??= new Function(args, 'return ' + expr); const value = fn(scope); return escape(value); } catch (e) { console.warn(`Template expression error in "{{${expr}}}":`, e); return ''; } });// 使用示例const works = "It_works";const uu = { message: 'use this message here. <test>', learnMore: 'learn more', link: 'dai sit ein link', target: '_self', markup: '{{uu.message}} test: {{works}} <a data-cc="uu.link" target="{{ uu.target }}" class="info" href="{{uu.link || "#null"}}">{{uu.learnMore}}</a>'};const result = insertReplacements(uu.markup, { uu, works });console.log(result);// 输出:// use this message here. <test> test: It_works <a data-cc="uu.link" target="_self" class="info" href="dai sit ein link">learn more</a>
该方案在保持简洁性的同时,兼顾了安全性、可维护性与执行效率,适用于轻量级模板引擎、配置化 UI 渲染等场景。