立即执行函数(iife)配合闭包实现脚本沙箱,核心是通过作用域隔离、显式依赖注入、闭包私有状态封装、高危api屏蔽及工厂函数实例化,构建轻量可控的执行环境。

用立即执行函数(IIFE)配合闭包实现脚本沙箱,核心在于隔离作用域、切断外部污染、控制内部暴露。这不是靠语法糖堆砌,而是靠作用域链的天然屏障和执行时机的精确把控。
用 IIFE 切断全局污染,建立独立作用域
IIFE 的本质是定义并立刻调用一个函数,它的执行上下文与外部完全隔离。只要不显式挂载到 window 或 globalThis,内部声明的变量、函数、类就不会泄漏。
- 写法必须带括号包裹:
(function(){ ... })();或(( ) => { ... })();,否则 JS 引擎会将其解析为函数声明而非函数表达式,导致语法错误 - 避免使用
var声明——它存在变量提升且作用域为函数级;优先用const和let,确保块级作用域清晰可控 - 若需传入依赖(如
console、JSON),应显式作为参数注入,而不是在内部直接访问全局对象
用闭包封装私有状态,只暴露最小必要接口
闭包让 IIFE 内部的变量能在返回的 API 函数中持续被引用,而外部无法直接访问这些变量。这是构建“绝对闭合”的关键机制。
- 把敏感数据(如配置、缓存、计数器)放在 IIFE 内部,不 return 出去
- 返回的对象或函数只包含明确设计的入口方法,例如:
{ run: () => {}, evalInSandbox: (code) => {} } - 所有内部辅助函数都保持私有——它们只是闭包中的“工具人”,不对外暴露名称或引用
限制执行环境,禁止隐式全局和危险操作
仅靠作用域隔离还不够。真正的沙箱必须防止代码通过 this、with、eval、Function 构造器等方式逃逸或污染。
- 在 IIFE 内部将
this绑定为一个空对象(Object.create(null)),避免意外访问全局this - 重写或屏蔽
eval、Function、setTimeout等高危原生方法,或抛出错误提示:“该操作在沙箱中被禁用” - 对传入的待执行代码做简单 AST 检查或正则过滤(如拦截
document.、window.、location.等敏感属性访问),不能替代完整沙箱引擎,但可防低级越界
支持动态加载与上下文继承,但不共享状态
真实场景中沙箱常需运行多段脚本,它们应能共享同一套受限 API,但彼此变量不能互相干扰。
- 把沙箱核心逻辑封装为工厂函数:
createSandbox({ allow: ['JSON', 'Math'] }),每次调用返回全新闭包实例 - 允许注入白名单 API(如只提供
JSON.stringify而不提供JSON.parse),且这些 API 是只读引用,无法篡改原始对象 - 若需跨脚本通信,统一走沙箱内置的消息通道(如
sandbox.emit()/sandbox.on()),而非共享变量或闭包外的全局事件总线











