with语句将对象临时添加到作用域链头部,使属性可直接访问,但因破坏词法作用域、阻碍编译优化、调试困难,ECMAScript 5严格模式下已被完全禁用,属已淘汰语法。
with 是 JavaScript 中一个被废弃的语法结构,它允许你临时将某个对象添加到作用域链头部,使得该对象的属性可以像局部变量一样直接访问。
比如:
const obj = { x: 1, y: 2 };
with (obj) {
console.log(x + y); // 不报错,x 和 y 被解析为 obj.x / obj.y
}
这看起来方便,但实际执行时,JS 引擎必须在每次读取 x 或 y 时,先检查它们是否是 obj 的自有属性,再沿作用域链向上查找——这个过程无法在编译期确定,导致所有相关变量访问都失去优化可能。
ECMAScript 5 开
始,with 在严格模式("use strict")中被完全禁止,尝试使用会抛出 SyntaxError: Strict mode code may not include a with statement。
原因很实际:
eval 类似,属于“破坏作用域透明性”的设计过去有人用 with 简化 DOM 操作或配置对象嵌套访问,例如:
with (document.getElementById('form').elements) {
username.value = '';
password.value = '';
}
这种写法现在应改用解构或显式引用:
const form = document.getElementById('form');
const { username, password } = form.elements;
username.value = '';
password.value = '';
或者更安全地逐个获取:
const form = document.getElementById('form');
form.elements.username?.value = '';
form.elements.password?.value = '';
要点:
with 来“省略前缀”no-with 错误虽然你不会主动写 with,但某些旧库或压缩后的代码(尤其是早期 Closure Compiler 输出)可能残留。另外,非严格模式下的浏览器控制台里仍可执行,但这不代表它安全。
真正容易被忽略的是:即使整个脚本没写 with,只要某处用了 eval 并传入含 with 的字符串,也会触发禁用逻辑或运行时错误——而这类间接调用极难排查。
所以不是“不推荐”,而是“已淘汰”。现在看到它,就当看见一段需要重构的遗留代码。