原型链查找与对象密封相互独立:密封仅限制自有属性的增删改配置,不干扰原型链查找;访问属性时仍会沿__proto__向上搜索,继承属性可正常读取和调用。

JavaScript 中,原型链查找和对象的密封状态(sealed)是两个独立但可能交互的概念:前者决定属性如何被读取,后者限制对象自身的可变性。密封状态不影响原型链查找行为,但会影响对当前对象属性的操作权限。
原型链查找:属性访问时的向上搜索机制
当访问一个对象的属性时,JavaScript 引擎会按以下顺序查找:
- 先检查对象自身是否拥有该属性(包括自有可枚举/不可枚举属性)
- 若没有,沿
__proto__(即Object.getPrototypeOf(obj))指向的原型对象继续查找 - 重复该过程,直到找到该属性,或原型链终点(
null)为止
注意:即使对象被密封,原型链查找照常进行;密封只阻止新增、删除和配置自身属性,不阻断读取——包括从原型继承来的属性。
对象密封(sealed):仅锁定自有属性的配置行为
调用 Object.seal(obj) 后,对象满足:
立即学习“Java免费学习笔记(深入)”;
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 所有自有属性变为不可配置(
configurable: false),无法 delete、无法修改 descriptor(如 writable → true/false) - 仍可修改自有属性的值(如果它是 writable)
- 无法添加新自有属性
- 原型链本身不受影响——可以改写
obj.__proto__,也能在原型上增删改属性
例如:const a = { x: 1 }; Object.seal(a); a.x = 2; // ✅ 允许;delete a.x; // ❌ 失败;a.y = 3; // ❌ 无效;a.__proto__.z = 4; // ✅ 原型可改
密封对象 + 原型链:常见误区澄清
开发者有时误以为密封后“属性就固定了”,其实不然:
- 继承来的属性仍可被覆盖:在密封对象上赋值同名属性,会创建新的自有属性(除非该属性在原型中是
writable: false且configurable: false) - 原型上的方法调用完全不受影响:如
a.toString()依然走原型链找到Object.prototype.toString -
in操作符和hasOwnProperty行为不同:'x' in a为 true(含继承),a.hasOwnProperty('x')只反映是否为自有属性(密封前后逻辑不变)
对比 freeze 和 preventExtensions
便于理解密封的定位:
-
preventExtensions:禁止新增属性,但已有属性仍可删、可重配置 -
seal:在 preventExtensions 基础上,把所有自有属性设为configurable: false -
freeze:在 seal 基础上,再把所有自有数据属性设为writable: false(访问器属性不受影响)
三者都不改变原型链结构,也不阻止通过原型访问属性。

















