Symbol.unscopables 与 with 语句仅存在单向控制关系:它专为 with 设计,作为属性屏蔽黑名单,决定哪些属性名不被自动引入 with 作用域;with 不改变 this 绑定,三者机制完全独立。

Symbol.unscopables 和 with 语句之间没有直接关系,它不会影响 this 绑定,也不改变 with 的作用域查找逻辑。
这是一个容易混淆的组合,因为三者(this、with、Symbol.unscopables)都涉及“作用域”或“属性访问”,但它们在语言机制中完全独立:
? with 语句的作用是什么?
with 会将一个对象临时添加到词法作用域链的前端,使该对象的自有属性(非原型链)可被直接引用,不通过点号或方括号:
const obj = { x: 1, y: 2 };
with (obj) {
console.log(x); // ✅ 1 —— 直接访问 obj.x
console.log(this === obj); // ❌ false —— this 未被改变!
}
⚠️ 注意:with 不修改 this 值。this 仍由调用方式决定(如全局/严格模式下为 undefined 或 globalThis),和 with 无关。
? Symbol.unscopables 是干什么的?
它是专为 with 设计的“黑名单”符号属性,用于告诉 with:“这些属性名不要被自动暴露到作用域中”。
它只在 with 内部起作用,且仅影响属性是否被提升为变量名,不影响 this、不参与原型查找、也不改变任何绑定规则。
const arr = [1, 2, 3];
arr[Symbol.unscopables] = { includes: true }; // 隐藏 includes
with (arr) {
console.log(length); // ✅ 3 —— length 不在 unscopables 中,可访问
console.log(includes(2)); // ❌ ReferenceError: includes is not defined
}
✅ 这里 includes 被屏蔽,不是因为找不到方法,而是 with 根本不把它挂进当前作用域 —— 所以连标识符解析都失败。
? this 绑定和这两者都没关系
-
this的值由函数如何被调用决定(obj.method()→this = obj;func()→ 严格模式undefined); -
with不改变调用方式,所以不改变this; -
Symbol.unscopables只是控制with是否把某个 key 当作局部变量名暴露,和this完全无关; - 即使你在
with中调用一个方法,this仍取决于该方法内部如何被调用,而不是with包裹了谁。
例如:
const obj = {
name: 'Alice',
say() { console.log(this.name); }
};
obj[Symbol.unscopables] = { say: true }; // 屏蔽 say
with (obj) {
// say(); // ❌ ReferenceError —— say 没被暴露,根本调用不了
obj.say(); // ✅ 'Alice' —— 显式调用,this 正常绑定为 obj
}
✅ 总结关键点
-
with仅改变标识符解析的作用域链,不改变this; -
Symbol.unscopables是with的配置开关,只决定“哪些属性名不被自动引入作用域”; -
this绑定由调用位置和方式决定,与with和Symbol.unscopables都无语法层面关联; -
Symbol.unscopables主要用于数组等内置对象的向后兼容(比如屏蔽Array.prototype.keys在with (arr)中暴露,避免污染作用域),现代代码应避免使用with。
? 补充:
with在严格模式下被禁止;Symbol.unscopables是 ES6 引入的底层机制,普通开发几乎无需手动设置。
不复杂但容易忽略本质——它们解决的是不同问题:with 是作用域 hack,unscopables 是它的微调开关,this 是运行时绑定规则。三者不在同一抽象层。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











