为何类实例直接包含getter属性?与MDN文档描述矛盾解惑
问题背景
测试类的Getter属性时,发现实际表现和MDN文档描述的直观感受有冲突:
Getter properties are defined on the prototype property of the class and are thus shared by all instances of the class.
(Getter属性定义在类的prototype属性上,因此被类的所有实例共享。)
但调试时能在类实例上直接看到getter属性,同时有两个核心疑问:
- 若getter仅存在于实例的原型中,为何getter函数中的
this指向实例k而非Kevin.prototype? - 为何
getc直接出现在类实例上?为何k的原型中的getc值显示为lambo而非undefined?
测试代码:
class Kevin { constructor(x) { this.age = x; this.car = "lambo" } get getc() { return this.car; } } const k = new Kevin(3);
疑问解答
1. 为什么实例调试视图里能看到getc?
这是浏览器调试工具的展示优化:为了方便开发者快速查看所有可访问的属性,工具会把原型链上的可枚举属性(包括getter)合并展示在实例视图中。但实际上getc并没有定义在实例k本身,你可以通过Object.hasOwn(k, 'getc')验证,返回结果是false,说明它确实是从Kevin.prototype继承来的。
2. 为什么getter中的this指向实例k?
MDN的描述完全正确:
A function used as getter or setter has its this bound to the object from which the property is being set or gotten.
(用作getter或setter的函数,其this会绑定到获取或设置该属性的对象。)
当你访问k.getc时,调用getter的上下文对象是实例k,哪怕getter本身定义在原型上,JavaScript会自动把this绑定到当前调用的实例。这也是原型属性能访问实例自身数据的核心逻辑。
3. 为什么原型中的getc显示为lambo?
调试工具在展示原型上的getter时,会主动调用该getter来展示当前的返回值。而调用时的this依然指向实例k(因为工具是通过实例k去访问原型上的getc),所以this.car取到的是实例的lambo,因此显示的是这个结果。
你可以通过Object.getOwnPropertyDescriptor(Kevin.prototype, 'getc')查看原型上的getc实际结构,会发现它只是一个getter函数,并没有存储具体值。
内容的提问来源于stack exchange,提问作者scorpian111

