第四章|对象模型
一个对象的行为由三件事共同决定:自身属性、原型连接,以及属性访问的规则。本章先解释普通查找,再学习 class 如何组织这些规则,最后进入描述符和代理。这样阅读 super、getter、Proxy 的 receiver 时,用的是同一套对象模型。
- 原型与属性查找:从“属性在哪里”推导读取、赋值、构造与身份判断。
- 类、继承与组合:组织独立状态,理解初始化顺序、私有字段和静态成员。
- 描述符与 Symbol:解释枚举、复制、冻结和协议定制。
- Proxy 与 Reflect:把普通访问模型延伸到拦截、转发和不变量。
读完应能沿原型链解释一次访问,也能指出“共享方法”与“共享可变状态”的区别。后两篇细节较密,可以先顺读关键例子,再在遇到枚举或代理问题时回查。练习只检验知识,不要求另做项目。
阅读前先连起三个问题
前面学过的 obj.method() 实际包含两步:读取属性,调用读取到的值。第一步决定去哪找方法,第二步决定 this。把这两步混在一起,才会误以为“方法属于哪个对象,this 就永远是谁”。本章从这条分界线出发,随后遇到继承访问器和 Proxy 的 receiver,仍沿同一条推理链。
读本章前需要会创建对象、声明函数,知道对象变量保存引用,并能区分函数调用与方法调用。如果数组共享的例子不好理解,先回想 const b = a 没有复制对象:原型只是增加了一条找到该引用的路径。
读写规则可以沿一条具体路径串联:先读实例自有字段,再沿原型找 getter;执行 getter 时仍使用原接收者;赋值遇到继承描述符时,还要检查真正接收写入的对象。class 的字段定义与 Proxy 的转发都会碰到这条路径,只是一个在初始化时直接定义属性,一个在运行时拦截相应操作。
本章的反例专门改变一项前提:把数据属性换成访问器、把可配置改为不可配置、把方法接收者换成别的对象。先预测哪个步骤会改变,再运行例子,比把成功和失败各记一条结论更容易迁移到未见过的代码。
从普通规则走向可定制规则
第一篇观察的是对象的默认行为;第二篇用 class 把实例初始化与共享方法组织起来;第三篇解释默认行为背后由哪些属性标志控制;第四篇才允许程序拦截操作。描述符还决定代理能否报告某个结果,因此 Proxy 的不变量并不是独立背诵表,而是在保护前面已经建立的承诺。
例如,一个冻结的自有属性保证不会变化,代理就不能读取出另一个值。反过来,普通的可扩展对象尚未作出这种承诺,代理可定制的空间也更大。阅读时可以不断问:当前操作查的是谁,执行时的接收者是谁,目标已经作出了哪些不可撤回的约束?
读完以后动手检查
读完后,用一个带独立列表与共享方法的小对象检验理解:能否改变实例状态而不影响另一实例,再解释复制描述符和加代理后哪些行为仍保持、哪些边界需要重新约定?各篇第四题把这些判断变成实现任务,先独立写,再用答案中的断言核对。