如何在Object.defineProperty定义的getter中实现super访问父类属性的效果
重写JS原型getter时super失效的解决方案
核心问题原因
super关键字仅支持在class方法、对象字面量的简写方法中使用,你传入Object.defineProperty的是普通匿名函数,不具备super的上下文绑定,因此无法直接调用父类的同名属性getter。
可行实现方案
通过Object.getOwnPropertyDescriptor查找父原型链上对应属性的描述符,调用get方法时绑定当前实例上下文即可,不需要提前存储getter引用,不会触发illegal invocation错误。
基础实现代码(父类直接定义prop的场景)
Object.defineProperty(func.prototype, "prop", { get: function () { // 获取func的父类原型 const parentProto = Object.getPrototypeOf(func.prototype); // 从父类原型上拿到prop的属性描述符 const parentPropDesc = Object.getOwnPropertyDescriptor(parentProto, "prop"); // 绑定当前实例调用父类getter,获取父类返回值 const x = parentPropDesc.get.call(this); // 自定义扩展逻辑 console.log(x); return x; } })
兼容多层继承的实现代码
如果存在多层继承、不确定prop在哪一层父原型上定义,可以封装查找逻辑向上遍历原型链:
// 向上遍历原型链查找指定属性的描述符 function findPrototypePropDesc(startProto, propName) { let currentProto = Object.getPrototypeOf(startProto); while (currentProto !== null) { const desc = Object.getOwnPropertyDescriptor(currentProto, propName); if (desc) return desc; currentProto = Object.getPrototypeOf(currentProto); } return undefined; } Object.defineProperty(func.prototype, "prop", { get: function () { const parentPropDesc = findPrototypePropDesc(func.prototype, "prop"); const x = parentPropDesc ? parentPropDesc.get.call(this) : undefined; console.log(x); return x; } })
方案合法性说明
我们没有将父类getter单独赋值为变量再无上下文调用,而是获取到get方法后立即绑定当前实例this执行,完全符合getter要求的调用上下文规则,不会抛出illegal invocation异常。
内容的提问来源于stack exchange,提问作者khizar ansari
相关产品推荐
相关产品推荐

