Learning Record
今日学习内容
今天学习了如何结合 JavaScript 的 with 语句和 Proxy 创建一个简单的运行沙盒,让代码优先从指定的沙盒对象中读取和修改变量,减少对全局作用域的直接影响。
实现思路
with 会把一个对象临时加入当前作用域链。配合 Proxy 后,可以拦截代码对变量的查询、读取和赋值操作,将这些操作限制在沙盒对象中。
function createSandbox(initialState = {}) {
const sandbox = new Proxy(
{ ...initialState },
{
has() {
return true;
},
get(target, key) {
if (key === Symbol.unscopables) {
return undefined;
}
return Reflect.get(target, key);
},
set(target, key, value) {
return Reflect.set(target, key, value);
},
}
);
return {
sandbox,
run(code) {
const execute = new Function("sandbox", `with (sandbox) { return (() => { ${code} })(); }`);
return execute(sandbox);
},
};
}
const context = createSandbox({ count: 1 });
context.run("count += 1; message = 'hello';");
console.log(context.sandbox.count); // 2
console.log(context.sandbox.message); // hello
console.log(globalThis.message); // undefined
核心原理
with (sandbox)让标识符优先在sandbox中查找Proxy的has拦截器让变量查询停留在沙盒对象中get和set拦截器负责读取与保存沙盒中的变量- 每个沙盒使用独立对象,因此不同沙盒之间的状态不会直接混在一起
注意事项
with + Proxy 只能实现基础的作用域隔离,并不等于真正的安全沙盒:
- 严格模式中不能使用
with with会让变量来源变得不清晰,也不利于 JavaScript 引擎优化- 如果向沙盒暴露了
window、globalThis、Function等对象,执行代码仍可能访问外部环境 - 不应该使用这种方式执行不可信代码
如果需要执行不可信代码,应选择隔离能力更强的方案,例如浏览器中的 iframe、Web Worker,或者 Node.js 中经过安全评估的隔离方案。
今日总结
今天理解了 with 可以改变标识符的查找范围,而 Proxy 可以控制变量的读取和写入。两者结合后能够实现一个简单的 JavaScript 沙盒,适合学习作用域和微前端沙盒的基本原理,但不能作为真正的安全边界。