with语句会将对象插入作用域链前端,导致变量查找顺序改变、同名属性遮蔽及赋值行为模糊,ES5严格模式已禁用;应改用解构赋值等清晰替代方案。

with 语句会临时将指定对象插入到当前作用域链的前端,使该对象的属性在语句块内可直接访问,无需通过对象名引用。但正因它动态修改作用域链,破坏了代码的可预测性和静态分析能力,ES5严格模式已禁止使用,现代JavaScript开发中应完全避免。
作用域链如何被with改变
正常函数执行时,作用域链由词法作用域决定:局部作用域 → 外层函数作用域 → 全局作用域。而 with 会在运行时把传入的对象“推入”作用域链最前端。这意味着:
- 变量查找先从该对象自身属性开始,再逐级向上;
- 若对象有同名属性(如 x),会遮蔽外层同名变量或全局变量;
- 赋值行为变得模糊:对未声明变量的赋值,可能写入该对象属性,也可能创建全局变量(非严格模式下)。
典型问题示例
以下代码在非严格模式下行为难以直观判断:
var obj = { x: 1 };
var x = 10;
with (obj) {
x = 2; // 修改 obj.x,不是外层 x
y = 3; // 创建全局 y(非严格模式)或报错(严格模式)
console.log(x); // 输出 2
}
console.log(x); // 仍为 10
console.log(obj.x); // 变为 2
这种隐式绑定让调试和维护成本大幅上升,工具(如压缩器、IDE自动补全、静态检查器)也无法准确推导变量来源。
立即学习“Java免费学习笔记(深入)”;
为什么严格模式禁用with
ES5严格模式明确禁止 with,原因包括:
- 无法进行有效的编译期优化(JIT引擎难以确定变量归属);
- 阻碍代码压缩和混淆(重命名变量时需额外规避对象属性冲突);
- 与 let/const 块级作用域、模块作用域等现代特性不兼容;
- 增加安全风险(如配合 eval 可能绕过作用域隔离)。
替代方案推荐
所有 with 场景均可更清晰地重构:
- 频繁访问对象属性 → 使用解构赋值:
const { prop1, prop2 } = obj; - 临时扩展作用域用于模板或配置 → 显式调用函数或使用箭头函数闭包;
- 历史遗留的 DOM 操作(如旧版 Prototype.js 风格)→ 改用现代 API 或封装方法,例如
el.style.color = 'red'替代with(el.style) { color = 'red' }。










