
本文介绍在纯 ES6 模块环境下,如何正确导入并动态求值包含模板字符串(如 ${params.xxx})的配置对象,避免 ReferenceError,同时规避 eval() 的安全风险,推荐使用函数式模板或 template literals 替代方案。
本文介绍在纯 es6 模块环境下,如何正确导入并动态求值包含模板字符串(如 `${params.xxx}`)的配置对象,避免 `referenceerror`,同时规避 `eval()` 的安全风险,推荐使用函数式模板或 `template literals` 替代方案。
在 ES6 模块系统中,import 语句会在模块加载时静态执行,所有导出值(包括对象字面量)都会被立即求值。因此,当你在 content.js 中这样定义:
// content.js
export const appText = {
item: {
message: `You're ${params.firstName} ${params.lastName}.` // ❌ params 未定义!
}
};
该模板字符串会在模块解析阶段尝试执行,此时 params 根本不存在,自然抛出 Uncaught ReferenceError: params is not defined。
✅ 正确做法:将模板逻辑延迟到运行时
方案一:使用函数式模板(推荐 ✅)
将模板封装为接收 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(messageElement) {
this.message = messageElement;
}
init(params) {
this.message.innerHTML = appText.item.message(params); // ✅ 延迟求值,安全可靠
}
}
✅ 优势:类型友好、可测试、无执行风险、支持 IDE 自动补全与 TypeScript 类型推导。
方案二:使用 String.raw + Function 构造器(谨慎使用 ⚠️)
若需保留原始字符串格式(如从 JSON 或 CMS 加载),可借助 Function 构造器安全构造模板函数(非 eval,不执行任意代码):
// content.js
export const appText = {
item: {
message: 'You\'re ${params.firstName} ${params.lastName}.'
}
};
// 工具函数(建议全局复用)
export const template = (str) => (params) =>
new Function('params', `return \`${str}\`;`)(params);
使用方式:
import { appText, template } from "../../content.js";
// 动态生成模板函数
const messageFn = template(appText.item.message);
this.message.innerHTML = messageFn(params); // ✅ 安全、可控
⚠️ 注意:Function 构造器虽比 eval 更隔离,但仍需确保 str 来源可信(如项目内硬编码或经校验的配置),切勿用于用户输入。
❌ 不推荐:eval()(高危 ❌)
原文提到的 eval('' + appText.item.message + '') 存在严重安全隐患:
- 执行任意 JavaScript 代码,易受 XSS 攻击;
- 破坏作用域隔离,影响调试与性能优化;
- 被现代 Linter(如 ESLint)默认禁止。
即使“文件受控”,也违背最小权限原则,应坚决避免。
总结
- 永远不要在模块顶层直接使用未定义变量的模板字符串;
- 首选函数式模板:message: (p) => \...\${p.x}``,清晰、安全、可维护;
- 如需字符串驱动模板,用 Function 构造器替代 eval,并严格校验输入;
- 在构建工具(Vite/Webpack)中,还可结合 import.meta.glob 或 JSON 导入进一步解耦配置与逻辑。
遵循以上实践,即可在纯 JS ES6 模块中优雅、安全地实现参数化文案管理。











