JavaScript 无法真正重塑 eval 作用域,因其是语法关键字;所谓“重塑”实为用 Function 构造函数模拟局部作用域:提取 context 键为参数、传 script 字符串、eval 内置防护防篡改,实现变量注入与隔离。

JavaScript 中无法真正“重塑” eval 的作用域,因为 eval 是语法关键字,不是普通函数,不支持 call/apply、不接受上下文绑定,也无法通过 with(已禁用)或代理方式直接重写词法环境。所谓“重塑”,实际是指**绕过 eval 默认作用域行为,构造一个可控的、隔离的执行环境**——核心方法是不用 eval,改用 Function 构造函数模拟局部作用域。
eval 本身的作用域不可控
eval 总是在调用它的词法作用域中执行: - 直接调用(如 eval('x = 1'))可读写当前函数或全局变量; - 间接调用(如 const e = eval; e('x = 1'))退化到全局,且行为不一致; - 严格模式下,eval 拥有独立作用域,内部声明不会污染外层,但仍无法注入变量; - with 虽能临时扩展作用域链,但已被严格模式禁止,且存在安全与性能问题,不可用。
Function 构造函数实现变量注入式“局部作用域”
这是目前最标准、安全、可移植的替代方案:把 context 对象的 key 当作函数参数名,value 当作实参传入,让 eval 在该函数体内运行,自然获得这些变量的访问权。 - 提取 Object.keys(context) 作为形参列表; - 将原始 script 字符串作为额外参数传入; - 函数体中执行 eval("script = undefined;" + script),加防护防篡改; - 所有变量仅存在于该函数的局部作用域,不泄漏、不污染。
关键防护与注意事项
- script = undefined; 必须写在 eval 内部开头,防止用户代码重赋值 script 参数导致逻辑绕过; - 传入的 context 值保持原生类型(对象、函数、Symbol 等),无需 JSON 序列化,避免类型丢失和拼接漏洞; - 该方案解决的是作用域隔离,不是沙箱:脚本仍可调用 fetch、localStorage、alert 等全局 API; - 若执行不可信代码,必须配合 VM2、Web Worker 或 iframe 沙箱等真正隔离机制; - 高频调用时可缓存 Function 实例(当 script 模板固定、仅变量变化时)。
为什么不推荐其他方式
- new Function(...).call(context) 无效:Function 创建的函数默认只访问全局,call 不改变其词法作用域; - Proxy + with 不可行:with 已被禁用,Proxy 无法拦截变量查找过程; - eval + IIFE 拼接字符串 易出错:JSON.stringify 会丢失函数、undefined、Symbol,且拼接易引入 XSS; - 动态生成 script 标签 运行在全局,无法注入变量,也不可控。
不复杂但容易忽略
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。

















