JavaScript父类存在同名实例属性时是否会忽略子类同名方法?
表现是否符合预期
该表现完全符合ECMAScript的标准规范,不属于异常。
背后的运行原理
核心原因是类公共实例字段和类原型方法的定义位置、初始化时机存在本质差异:
- Base类中
get = () => {}属于公共实例字段,会在类实例化阶段(调用super()时)直接作为属性挂载到生成的实例对象自身,不是定义在Base.prototype上的原型方法 - Child类中
get() {}属于原型方法,只会挂载到Child.prototype上,不会出现在实例对象自身
JS访问对象属性的优先级是:先查找对象自身的属性,找不到才会沿原型链向上查找。调用child.get()时,优先匹配到了实例自身由Base类初始化生成的get箭头函数,自然不会触发原型链上Child的get方法。
更合理的实现方案
你当前的实现会在实例上新增公开的parentGet属性,污染实例命名空间,推荐用私有属性存储父类方法的方案,不会对外暴露内部存储的父类方法:
class Base { get = () => { console.log('i am the Base function'); } } class Child extends Base { // 声明私有属性存储父类get方法,外部无法访问修改 #parentGet; constructor() { super(); // super执行完成后,父类的get已经挂载到实例,先存储再覆盖 this.#parentGet = this.get; } // 子类的实例字段赋值在super之后执行,直接覆盖父类的get属性 get = () => { console.log('i am the Child function'); this.#parentGet(); } } const child = new Child(); child.get(); // 先输出'i am the Child function',再输出'i am the Base function'
如果你的运行环境不支持ES私有属性,可以用Object.defineProperty结合闭包的方案实现,不会在实例上新增额外可访问属性:
class Child extends Base { constructor() { super(); const parentGet = this.get; Object.defineProperty(this, 'get', { enumerable: true, configurable: true, value: () => { console.log('i am the Child function'); parentGet(); } }) } }
内容的提问来源于stack exchange,提问作者tomsidorov
相关产品推荐
相关产品推荐

