心智为 9 岁的 ChatGPT 大约相当于我们小学 3 年级的学生,所以让我们与小学 3 年级的 ChatGPT 一起来深入学习编程吧.
下面是对 ChatGPT 的第一次提问:
你知道吗?编写一个 js 函数模拟实现 super 访问父类方法的功能有几种方法?哪一种方法从语法上最接近原生super?
要求:该函数的调用方式要从语法上尽可能的接近原生super的调用方式,实现尽量简洁明了.
其中约定实现的函数名以及函数签名(返回值根据具体实现方式而定)为: getSuper(instance: Object)
ChatGPT 的第一次回答
实现 super 访问父类方法的功能有以下几种方法:
-
使用
Object.getPrototypeOf和Object.getOwnPropertyDescriptor方法来获取父类的属性描述符,从而获取父类方法,并使用Function.prototype.call方法来调用该方法:function getSuper(instance) { const proto = Object.getPrototypeOf(instance); const descriptor = Object.getOwnPropertyDescriptor(proto, arguments.callee.caller.name); if (descriptor) { const superFunc = descriptor.value; return function(...args) { return superFunc.call(instance, ...args); }; } } -
使用原型链
Object.getPrototypeOf()和Reflect.getPrototypeOf()都可以获取原型对象,但是Reflect.getPrototypeOf()可以在 Proxy 对象上获取正确的原型对象,因此使用Reflect.getPrototypeOf()可以增强代码的兼容性。具体实现代码如下:function getSuper(instance) { const prototype = Reflect.getPrototypeOf(instance); return function(methodName, ...args) { const parentPrototype = Reflect.getPrototypeOf(prototype); const parentMethod = parentPrototype[methodName]; if (typeof parentMethod === 'function') { return parentMethod.call(instance, ...args); } } } -
使用 ES6 的
Proxy对象来代理子类实例的属性访问和方法调用。当子类实例的属性或方法不存在时,通过代理对象访问父类实例的属性或方法:function getSuper(instance) { return new Proxy(instance, { get(target, prop) { if (prop in target) { return target[prop]; } else if (prop in Object.getPrototypeOf(target)) { const superProp = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(target), prop); if (superProp.hasOwnProperty('value')) { return (...args) => superProp.value.call(target, ...args); } else { return superProp.get.call(target); } } } }); } class Parent { constructor() { this.parentProperty = 'parent property'; } parentMethod() { return 'parent method'; } } class Child extends Parent { constructor() { super(); this.childProperty = 'child property'; } childMethod() { const superMethod = getSuper(this).parentMethod; return `child method calling parent method: ${superMethod()}`; } } const childInstance = new Child(); console.log(childInstance.childMethod()); // Output: "child method calling parent method: parent method"
样例类:
class Root {
constructor(name) {
this.name = name;
}
hi(n) {
console.log(`hi ${n} ${this.name} from Root`);
}
}
class A extends Root {
hi() {
console.log(`hi from A`)
super.hi("here") //replace this
}
let a = new A('Mike')
a.hi('here') // print 'hi here from A' and 'hi Mike from Root'
引导提问 1
ChatGPT, 你之前的回答中各个方法中都存在问题,思考下.
那么,如何实现 super 访问父类方法的功能,你们怎么看?