为何JavaScript中getter/setter触发栈溢出后代码仍能正常运行?
问题解析:为什么同名属性与get/set未触发递归栈溢出
你的代码里根本没触发定义的get msg()和set msg()方法,自然不会出现递归栈溢出问题,核心原因在于实例自身的数据属性屏蔽了原型上的访问器属性:
- 类中的
msg = 'Hello'是实例公共字段,当创建instance实例时,这条语句会直接在实例对象自身上添加一个名为msg的数据属性,初始值为'Hello'。 - 而你定义的
get msg()和set msg()是挂载在ClassWithGetSet类的原型对象上的访问器属性。 - JavaScript的属性查找规则是:访问对象属性时,优先查找实例自身的属性,找到就直接返回或赋值;只有当实例自身没有该属性时,才会沿着原型链向上查找对应的访问器或数据属性。
所以你的代码实际执行流程是:
console.log(instance.msg):直接读取实例自身的msg属性,输出'Hello',完全没触发原型上的getter。instance.msg = 'Sandra':直接修改实例自身的msg属性值为'Sandra',也没触发原型上的setter。- 第二次
console.log(instance.msg):还是读取实例自身修改后的msg值,输出'Sandra'。
如果想让get/set访问器生效,你需要避免在实例自身添加同名数据属性,通常的做法是使用内部私有字段(比如用下划线前缀命名),然后在访问器中操作这个字段:
class ClassWithGetSet{ _msg = 'Hello'; get msg(){ return this._msg; } set msg(x){ this._msg = `Hello ${x}`; } } const instance = new ClassWithGetSet(); console.log(instance.msg); // 输出 'Hello' instance.msg = 'Sandra'; console.log(instance.msg); // 输出 'Hello Sandra'
内容的提问来源于stack exchange,提问作者Ana
相关产品推荐
相关产品推荐

