如何在ES6严格模式下替代with语句实现作用域内代码求值
解决ES6严格模式下替代
with实现作用域内代码执行的问题 原代码依赖with语句将上下文对象作为作用域,但严格模式下with被禁用,导致代码失效。以下是两种符合ES6严格模式规范的替代方案:
方案1:利用new Function动态注入上下文属性作为参数
这种方式通过将上下文对象的属性作为函数参数传入,让执行代码可以直接访问变量,完全兼容严格模式:
function evalInScope(js, contextAsScope) { const [keys, values] = [Object.keys(contextAsScope), Object.values(contextAsScope)]; return new Function(...keys, js)(...values); } // 测试用例 console.log(evalInScope("a + b", {a: 1, b: 2})); // 3 console.log(evalInScope("Math.min(x, y)", {x: 3, y: 1})); // 1
优势:实现简单,性能优异,无额外运行时开销;
局限:需要提前枚举上下文属性,若上下文属性动态变化,需重新调用函数。
方案2:使用Proxy拦截变量查找(支持动态属性)
如果需要支持动态添加的上下文属性,或不想提前枚举属性,可以用Proxy拦截变量读取操作,从上下文对象中获取对应值:
function evalInScope(js, contextAsScope) { const proxy = new Proxy(contextAsScope, { get(target, prop) { if (prop in target) { return target[prop]; } throw new ReferenceError(`${String(prop)} is not defined`); } }); return new Function(`return (${js})`).call(proxy); } // 测试用例 console.log(evalInScope("a + b", {a: 1, b: 2})); // 3 // 支持动态添加属性 const ctx = {foo: 5}; ctx.bar = 10; console.log(evalInScope("foo * bar", ctx)); // 50
优势:支持动态属性,无需提前枚举;
局限:Proxy存在轻微性能开销,适合上下文属性频繁变化的场景。
重要提示
- 动态执行代码(
eval/new Function)存在安全风险,务必仅执行可信代码,防止注入攻击; - 两种方案均完全符合ES6严格模式规范,可直接在默认启用严格模式的环境中运行;
- 若上下文包含嵌套对象,两种方案都支持通过
obj.prop的语法访问嵌套属性(如evalInScope("user.age", {user: {age: 25}}))。
内容的提问来源于stack exchange,提问作者kungfooman
相关产品推荐
相关产品推荐

