为何实例对象中出现age getter?它应仅存在于原型中
核心结论
你看到的age getter出现在实例对象里,不是因为getter被当成常规属性,也不是继承或super的问题,而是浏览器控制台的显示逻辑导致的视觉误解——age本质仍然是定义在PersonCl原型上的访问器属性,并没有被添加到实例自身。
具体解释
访问器属性的本质
类中定义的get/set属于访问器属性,和普通的实例数据属性(比如你定义的birthYear、course)不同,它们会被挂载到类的原型对象上,而不是实例自身。这一点和类中的普通方法(比如calcAge、greet)是一致的。控制台的“展平”显示
当你用console.log(martha)打印实例时,浏览器为了让你更直观地看到所有可访问的属性,会把原型链上的访问器属性“展平”显示在实例对象的视图中,但这并不代表这些属性属于实例自身。你可以通过以下代码验证:// 检查age是否是martha自身的属性 console.log(Object.hasOwn(martha, 'age')); // 输出false // 检查age是否在PersonCl的原型上 console.log(Object.hasOwn(PersonCl.prototype, 'age')); // 输出true继承与super的作用
super(fullName, birthYear)的作用只是调用父类PersonCl的构造函数,初始化实例的_fullName和birthYear属性,并没有将agegetter添加到实例上。继承机制是让StudentCl.prototype的原型指向PersonCl.prototype,所以martha的原型链是:martha → StudentCl.prototype → PersonCl.prototype
你可以通过以下代码验证原型链关系:console.log(martha.__proto__.__proto__ === PersonCl.prototype); // 输出true和普通方法的对比
你会发现calcAge、greet这些普通方法不会在实例视图中显示,但它们同样存在于PersonCl的原型上。这是因为控制台对访问器属性和普通方法的显示策略不同,但本质上两者都是原型成员。
总结
无需担心你的代码逻辑错误,age getter仍然正确地存在于父类原型上。控制台的显示只是为了方便开发者快速查看所有可访问属性,并非属性实际的存储位置。
内容的提问来源于stack exchange,提问作者Bilal Zahid Shah

