访问器属性在原型继承中不被复制,而是动态沿原型链委托查找;子类未重写时自动调用父类访问器,重写后可用super.fullname复用父逻辑,静态访问器同理。

访问器属性(getter/setter)在原型继承中不被“复制”,而是每次访问时动态沿原型链查找执行,本质是委托而非继承。处理的关键在于理解它的查找逻辑、遮蔽规则和潜在陷阱。
访问器始终走原型链查找
当对象自身没有定义同名访问器,但原型上有 getter 或 setter,读写操作会自动触发原型上的函数。这和数据属性的“遮蔽”不同——即使子对象没定义访问器,也不会把原型的 getter/setter 拷贝过来,而是持续委托。
- 子对象未定义 fullName 的 getter → 读取时调用原型上的 get fullName
- 子对象只定义了 set fullName,没定义 get → 读取返回 undefined(找不到 getter),写入仍走自己的 setter
- 子对象同时定义了 get 和 set → 完全遮蔽原型,所有访问都走自身的逻辑
避免数据属性意外覆盖访问器
这是最易出错的地方:如果父类用 getter 控制某个属性(比如 fullName),而子对象直接赋值 obj.fullName = "xxx",结果取决于父类 setter 是否存在:
- 父类有 setter → 按预期拆分、赋值,行为可控
- 父类无 setter → 赋值会在子对象上创建一个同名数据属性,从此遮蔽原型 getter,后续读取变成普通字符串,逻辑失效
建议在 setter 中做校验,或用 Object.defineProperty 显式设 writable: false, configurable: false 禁止意外写入。
ES6 class 让访问器继承更清晰
使用 class 语法声明的访问器,默认 configurable: true,支持安全重写,并能通过 super 显式调用父级逻辑:
- 子类不重写时,自动沿 [[Prototype]] 查找父类访问器
- 子类用
get fullName()重写后,可用super.fullName(注意不是super.fullName())复用父逻辑 - 静态访问器也遵循同样规则,查找路径是构造函数的原型链
在原型上定义访问器要谨慎
用 Object.defineProperty 给原型添加访问器时,必须显式设 configurable: true(默认为 false),否则子类无法重新定义同名属性,后续修改会抛错。
- 推荐统一在类定义阶段或构造函数中设置,避免运行时反复操作原型
- ES6 class 中用 get/set 声明的访问器天然满足该要求,更安全可靠











