JavaScript实现作用域隔离的核心是让动态代码在干净闭包中执行:用Function构造函数配合参数注入可控变量;禁用eval和with;复杂场景用Proxy沙箱或Node.js的vm模块。

JavaScript 中动态执行代码(比如 eval、Function 构造函数、setTimeout 字符串参数等)默认会访问当前作用域,容易污染变量或被外部变量干扰。要实现“作用域隔离”,核心思路是:**不把动态代码直接丢进当前作用域执行,而是让它运行在一个干净、受控的闭包环境中**。
用 Function 构造函数 + 闭包封装
Function 构造函数创建的函数具有词法作用域,但它的作用域链只包含全局作用域(不包含外层函数作用域),天然比 eval 更隔离。再配合立即执行闭包,就能注入可控的局部变量:
例如,你想让一段动态 JS 只能访问 api 和 utils,不能读写当前函数的 temp 或全局 window:
const api = { fetch: () => 'ok' };
const utils = { log: console.log };
// 动态脚本内容(字符串)
const script = "return utils.log('call'), api.fetch();";
// 构造一个仅暴露指定变量的函数
const safeFn = new Function('api', 'utils', script);
// 在隔离环境中调用
const result = safeFn(api, utils); // ✅ 安全执行,无法访问外部变量
避免 eval,绝不使用 with
eval 会继承当前作用域,且无法限制可访问变量;with 虽能临时扩展作用域链,但已被严格模式禁用,且行为不可预测、性能差、调试困难。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
❌ 错误示范:
const temp = 'leak';
eval("console.log(temp)"); // 能访问到 temp —— 不隔离
with ({ api }) {
eval("api.fetch()"); // 严格模式报错,非严格模式也难维护
}
需要更复杂环境?用沙箱对象 + Proxy 拦截(轻量级)
如果动态脚本需访问“类全局”对象(如 console、Date、JSON),又想禁止访问真实全局,可用 Proxy 拦截属性访问,返回白名单内的安全副本:
例如构建一个只允许使用 console.log、JSON.stringify、Date.now 的沙箱:
const globalWhitelist = {
console: { log: console.log.bind(console) },
JSON: { stringify: JSON.stringify },
Date: { now: Date.now }
};
const sandbox = new Proxy(globalWhitelist, {
has: (obj, prop) => prop in obj,
get: (obj, prop) => obj[prop],
set: () => false // 禁止写入
});
const script = "console.log(JSON.stringify({ t: Date.now() }));";
new Function('sandbox', script)(sandbox); // ✅ 执行在受限环境中
注意 Node.js 中的 vm 模块(服务端专用)
Node.js 提供 vm 模块,支持真正隔离的上下文(类似浏览器 iframe):
const vm = require('vm');
const context = vm.createContext({
api: { fetch: () => 'server ok' },
console: { log: console.log.bind(console) }
});
vm.runInContext('console.log(api.fetch())', context); // ✅ 全局变量完全隔离
⚠️ 注意:vm 并不绝对安全(仍可能通过原型链逃逸),生产环境处理不可信代码时,应配合进程隔离(如子进程)或容器化方案。

















