
本文介绍在纯 javascript(es6 modules)环境下,如何正确导入含参数占位符的配置对象,并在运行时安全求值,避免 referenceerror,同时规避 eval() 的安全风险。
本文介绍在纯 javascript(es6 modules)环境下,如何正确导入含参数占位符的配置对象,并在运行时安全求值,避免 referenceerror,同时规避 eval() 的安全风险。
在使用 ES6 模块导入配置对象(如多语言文案、提示消息等)时,一个常见需求是:配置内容需支持动态插入运行时参数(例如用户姓名),但直接在导出对象中引用未定义的变量(如 params.firstName)会导致模块加载时报错:Uncaught ReferenceError: params is not defined。这是因为模块顶层代码在导入时即执行,而 params 仅在组件实例方法(如 init())中才存在。
根本原因在于:JS 模块的导出值必须是静态可解析的,不能依赖导入方的作用域变量。因此,appText.item.message 不能直接包含未声明的 params——它不属于该模块作用域。
✅ 推荐方案:函数式模板(安全、类型友好、可测试)
将模板定义为纯函数,接收参数并返回渲染后的字符串:
// content.js
export const appText = {
item: {
message: (params) => `You're ${params.firstName} ${params.lastName}.`
}
};
// importer.js
import { appText } from "../../content.js";
export class Item {
constructor(messageEl) {
this.message = messageEl;
}
init(params) {
// 安全调用:params 在运行时传入,作用域清晰
this.message.innerHTML = appText.item.message(params);
}
}
✅ 优势:
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 无 eval,无 XSS 风险;
- 支持 TypeScript 类型推导(可为 (params: { firstName: string; lastName: string }) => string);
- 易于单元测试(直接调用函数并断言输出);
- 符合模块静态分析规范,兼容所有构建工具(Vite、Webpack、ESBuild)。
⚠️ 不推荐方案:eval() 或字符串拼接
虽然技术上可行,但存在严重隐患:
// ❌ 危险示例(勿用)
message: 'You\'re ${params.firstName} ${params.lastName}.',
// ...
this.message.innerHTML = eval('`' + appText.item.message + '`'); // 注入风险!
⚠️ 风险包括:
- 若配置内容来自外部(如 CMS、用户输入),极易触发任意代码执行;
- 破坏 CSP(Content Security Policy)策略;
- 无法进行静态检查与 tree-shaking;
- 调试困难,错误堆栈指向 eval 内部而非原始位置。
? 进阶:支持更复杂模板(可选)
若需更灵活语法(如 Handlebars 风格),可引入轻量模板引擎(如 mustache),或封装简易模板函数:
// utils.js
export function template(str, data) {
return str.replace(/\$\{([^}]+)\}/g, (_, key) => data[key.trim()] ?? '');
}
// content.js
export const appText = {
item: {
message: 'You\'re ${firstName} ${lastName}.'
}
};
// importer.js
import { template } from './utils.js';
// ...
this.message.innerHTML = template(appText.item.message, params);
总结
- 永远避免在模块顶层引用导入方变量;
- 用函数替代字符串模板——这是最简洁、安全、符合现代 JS 实践的解法;
- 拒绝 eval 和 Function 构造器处理不可信模板;
- 将“数据”与“渲染逻辑”分离,让配置真正成为可复用、可测试、可维护的纯数据结构。










