
本文讲解如何让 eval() 动态执行的代码中定义的函数,能被 setInterval 正确调用,重点解决模块脚本下作用域隔离导致的函数不可访问问题,并提供安全、可维护的替代方案。
本文讲解如何让 `eval()` 动态执行的代码中定义的函数,能被 `setInterval` 正确调用,重点解决模块脚本下作用域隔离导致的函数不可访问问题,并提供安全、可维护的替代方案。
在 JavaScript 模块(<script type="module">)环境中,eval() 执行的代码默认运行在全局作用域之外的独立词法环境中,其内部声明的变量和函数不会自动暴露到外部作用域,因此直接写 function examplefunc(){...} 后试图通过 code.examplefunc 访问会失败——因为 eval() 返回值默认是最后一条语句的执行结果,而非一个包含所有声明的对象。
正确做法是:显式构造一个对象,将目标函数作为其属性返回。例如:
const input = document.getElementById("codearea").value;
// ✅ 推荐:eval 返回一个带命名函数的对象
const code = eval(`({ examplefunc() { console.log('running'); } })`);
setInterval(() => code.examplefunc(), 10); // 安全调用⚠️ 注意事项:
- ❌ 避免 eval("function examplefunc(){...}") —— 返回 undefined,且函数无法导出;
- ✅ 使用对象字面量包裹(如 ({ examplefunc: ... }) 或 {examplefunc(){...}}),确保 eval() 返回可访问的对象;
- ⚠️ setInterval(code.examplefunc, 10) 存在 this 绑定丢失风险,建议使用箭头函数或 .bind(code) 包装;
- ? eval() 存在严重安全与性能隐患:执行任意用户输入代码可能导致 XSS、内存泄漏或调试困难,生产环境应禁用。
✅ 更优替代方案(强烈推荐):
// 使用 Function 构造函数(更可控、无副作用)
const fnBody = document.getElementById("codearea").value.trim();
const safeFunc = new Function('return ' + fnBody)(); // 假设输入为 ({ examplefunc: ... })
if (typeof safeFunc.examplefunc === 'function') {
setInterval(safeFunc.examplefunc.bind(safeFunc), 10);
}或彻底规避动态代码执行,改用配置化设计:
// 预定义安全函数库,用户仅选择行为
const safeFunctions = {
blink: () => document.body.style.opacity =
(parseFloat(document.body.style.opacity) || 1) > 0.5 ? '0.3' : '1',
logTime: () => console.log(new Date().toISOString())
};
const selected = safeFunctions[document.getElementById("funcSelect").value];
if (selected) setInterval(selected, 10);总结:eval() 不是跨作用域导出函数的可靠手段;务必通过对象封装显式暴露接口,并优先采用 Function 构造器或声明式 API 替代,兼顾功能、安全与可维护性。


















